diff options
author | 2017-02-05 13:56:35 +0100 | |
---|---|---|
committer | 2017-02-05 13:56:35 +0100 | |
commit | 1607745432f50099711d7aee355111111e66ff51 (patch) | |
tree | c4eaec8008f6e0283ca652cdffb55a34eca9b9bb /3rdparty/bx | |
parent | 193e8c8a89a4be5c63909cdbbcca4d9d6f8fee02 (diff) |
Update BGFX and BX (nw)
Diffstat (limited to '3rdparty/bx')
74 files changed, 11283 insertions, 6565 deletions
diff --git a/3rdparty/bx/include/bx/allocator.h b/3rdparty/bx/include/bx/allocator.h index f74b78b2c59..a1ab3e30826 100644 --- a/3rdparty/bx/include/bx/allocator.h +++ b/3rdparty/bx/include/bx/allocator.h @@ -8,7 +8,6 @@ #include "bx.h" -#include <memory.h> #include <string.h> //::memmove #include <new> @@ -42,18 +41,6 @@ namespace bx { - /// Aligns pointer to nearest next aligned address. _align must be power of two. - inline void* alignPtr(void* _ptr, size_t _extra, size_t _align = BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT) - { - union { void* ptr; size_t addr; } un; - un.ptr = _ptr; - size_t unaligned = un.addr + _extra; // space for header - size_t mask = _align-1; - size_t aligned = BX_ALIGN_MASK(unaligned, mask); - un.addr = aligned; - return un.ptr; - } - struct BX_NO_VTABLE AllocatorI { virtual ~AllocatorI() = 0; @@ -68,79 +55,84 @@ namespace bx virtual void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) = 0; }; - inline AllocatorI::~AllocatorI() - { - } - - inline void* alloc(AllocatorI* _allocator, size_t _size, size_t _align = 0, const char* _file = NULL, uint32_t _line = 0) - { - return _allocator->realloc(NULL, _size, _align, _file, _line); - } - - inline void free(AllocatorI* _allocator, void* _ptr, size_t _align = 0, const char* _file = NULL, uint32_t _line = 0) - { - _allocator->realloc(_ptr, 0, _align, _file, _line); - } - - inline void* realloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align = 0, const char* _file = NULL, uint32_t _line = 0) - { - return _allocator->realloc(_ptr, _size, _align, _file, _line); - } - - static inline void* alignedAlloc(AllocatorI* _allocator, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0) - { - size_t total = _size + _align; - uint8_t* ptr = (uint8_t*)alloc(_allocator, total, 0, _file, _line); - uint8_t* aligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align); - uint32_t* header = (uint32_t*)aligned - 1; - *header = uint32_t(aligned - ptr); - return aligned; - } - - static inline void alignedFree(AllocatorI* _allocator, void* _ptr, size_t /*_align*/, const char* _file = NULL, uint32_t _line = 0) - { - uint8_t* aligned = (uint8_t*)_ptr; - uint32_t* header = (uint32_t*)aligned - 1; - uint8_t* ptr = aligned - *header; - free(_allocator, ptr, 0, _file, _line); - } - - static inline void* alignedRealloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0) - { - if (NULL == _ptr) - { - return alignedAlloc(_allocator, _size, _align, _file, _line); - } - - uint8_t* aligned = (uint8_t*)_ptr; - uint32_t offset = *( (uint32_t*)aligned - 1); - uint8_t* ptr = aligned - offset; - size_t total = _size + _align; - ptr = (uint8_t*)realloc(_allocator, ptr, total, 0, _file, _line); - uint8_t* newAligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align); - - if (newAligned == aligned) - { - return aligned; - } - - aligned = ptr + offset; - ::memmove(newAligned, aligned, _size); - uint32_t* header = (uint32_t*)newAligned - 1; - *header = uint32_t(newAligned - ptr); - return newAligned; - } + /// Check if pointer is aligned. _align must be power of two. + bool isAligned(const void* _ptr, size_t _align); + /// Aligns pointer to nearest next aligned address. _align must be power of two. + void* alignPtr( + void* _ptr + , size_t _extra + , size_t _align = BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT + ); + + /// + void* alloc( + AllocatorI* _allocator + , size_t _size + , size_t _align = 0 + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// + void free( + AllocatorI* _allocator + , void* _ptr + , size_t _align = 0 + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// + void* realloc( + AllocatorI* _allocator + , void* _ptr + , size_t _size + , size_t _align = 0 + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// + void* alignedAlloc( + AllocatorI* _allocator + , size_t _size + , size_t _align + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// + void alignedFree( + AllocatorI* _allocator + , void* _ptr + , size_t /*_align*/ + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// + void* alignedRealloc( + AllocatorI* _allocator + , void* _ptr + , size_t _size + , size_t _align + , const char* _file = NULL + , uint32_t _line = 0 + ); + + /// template <typename ObjectT> - inline void deleteObject(AllocatorI* _allocator, ObjectT* _object, size_t _align = 0, const char* _file = NULL, uint32_t _line = 0) - { - if (NULL != _object) - { - _object->~ObjectT(); - free(_allocator, _object, _align, _file, _line); - } - } + void deleteObject( + AllocatorI* _allocator + , ObjectT* _object + , size_t _align = 0 + , const char* _file = NULL + , uint32_t _line = 0 + ); } // namespace bx +#include "allocator.inl" + #endif // BX_ALLOCATOR_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/allocator.inl b/3rdparty/bx/include/bx/allocator.inl new file mode 100644 index 00000000000..67a4a5325c5 --- /dev/null +++ b/3rdparty/bx/include/bx/allocator.inl @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_ALLOCATOR_H_HEADER_GUARD +# error "Must be included from bx/allocator.h" +#endif // BX_ALLOCATOR_H_HEADER_GUARD + +namespace bx +{ + inline AllocatorI::~AllocatorI() + { + } + + inline bool isAligned(const void* _ptr, size_t _align) + { + union { const void* ptr; uintptr_t addr; } un; + un.ptr = _ptr; + return 0 == (un.addr & (_align-1) ); + } + + inline void* alignPtr(void* _ptr, size_t _extra, size_t _align) + { + union { void* ptr; uintptr_t addr; } un; + un.ptr = _ptr; + uintptr_t unaligned = un.addr + _extra; // space for header + uintptr_t mask = _align-1; + uintptr_t aligned = BX_ALIGN_MASK(unaligned, mask); + un.addr = aligned; + return un.ptr; + } + + inline void* alloc(AllocatorI* _allocator, size_t _size, size_t _align, const char* _file, uint32_t _line) + { + return _allocator->realloc(NULL, _size, _align, _file, _line); + } + + inline void free(AllocatorI* _allocator, void* _ptr, size_t _align, const char* _file, uint32_t _line) + { + _allocator->realloc(_ptr, 0, _align, _file, _line); + } + + inline void* realloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) + { + return _allocator->realloc(_ptr, _size, _align, _file, _line); + } + + inline void* alignedAlloc(AllocatorI* _allocator, size_t _size, size_t _align, const char* _file, uint32_t _line) + { + size_t total = _size + _align; + uint8_t* ptr = (uint8_t*)alloc(_allocator, total, 0, _file, _line); + uint8_t* aligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align); + uint32_t* header = (uint32_t*)aligned - 1; + *header = uint32_t(aligned - ptr); + return aligned; + } + + inline void alignedFree(AllocatorI* _allocator, void* _ptr, size_t _align, const char* _file, uint32_t _line) + { + BX_UNUSED(_align); + uint8_t* aligned = (uint8_t*)_ptr; + uint32_t* header = (uint32_t*)aligned - 1; + uint8_t* ptr = aligned - *header; + free(_allocator, ptr, 0, _file, _line); + } + + inline void* alignedRealloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) + { + if (NULL == _ptr) + { + return alignedAlloc(_allocator, _size, _align, _file, _line); + } + + uint8_t* aligned = (uint8_t*)_ptr; + uint32_t offset = *( (uint32_t*)aligned - 1); + uint8_t* ptr = aligned - offset; + size_t total = _size + _align; + ptr = (uint8_t*)realloc(_allocator, ptr, total, 0, _file, _line); + uint8_t* newAligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align); + + if (newAligned == aligned) + { + return aligned; + } + + aligned = ptr + offset; + ::memmove(newAligned, aligned, _size); + uint32_t* header = (uint32_t*)newAligned - 1; + *header = uint32_t(newAligned - ptr); + return newAligned; + } + + template <typename ObjectT> + inline void deleteObject(AllocatorI* _allocator, ObjectT* _object, size_t _align, const char* _file, uint32_t _line) + { + if (NULL != _object) + { + _object->~ObjectT(); + free(_allocator, _object, _align, _file, _line); + } + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/bx.h b/3rdparty/bx/include/bx/bx.h index 65a50d08cb4..43ccba3cce1 100644 --- a/3rdparty/bx/include/bx/bx.h +++ b/3rdparty/bx/include/bx/bx.h @@ -8,7 +8,7 @@ #include <stdint.h> // uint32_t #include <stdlib.h> // size_t -#include <string.h> // memcpy +#include <stddef.h> // ptrdiff_t #include "config.h" #include "macros.h" @@ -45,39 +45,23 @@ namespace bx Ty tmp = _a; _a = _b; _b = tmp; } - /// Check if pointer is aligned. _align must be power of two. - inline bool isPtrAligned(const void* _ptr, size_t _align) - { - union { const void* ptr; size_t addr; } un; - un.ptr = _ptr; - return 0 == (un.addr & (_align-1) ); - } + /// + void* memCopy(void* _dst, const void* _src, size_t _numBytes); - /// Scatter/gather memcpy. - inline void memCopy(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch, uint32_t _dstPitch) - { - const uint8_t* src = (const uint8_t*)_src; - uint8_t* dst = (uint8_t*)_dst; - - for (uint32_t ii = 0; ii < _num; ++ii) - { - memcpy(dst, src, _size); - src += _srcPitch; - dst += _dstPitch; - } - } + /// + void memCopy(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch, uint32_t _dstPitch); /// - inline void gather(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch) - { - memCopy(_dst, _src, _size, _num, _srcPitch, _size); - } + void gather(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch); /// - inline void scatter(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _dstPitch) - { - memCopy(_dst, _src, _size, _num, _size, _dstPitch); - } + void scatter(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _dstPitch); + + /// + void* memMove(void* _dst, const void* _src, size_t _numBytes); + + /// + void* memSet(void* _dst, uint8_t _ch, size_t _numBytes); } // namespace bx diff --git a/3rdparty/bx/include/bx/commandline.h b/3rdparty/bx/include/bx/commandline.h index bafd48e3be2..9b9a397360b 100644 --- a/3rdparty/bx/include/bx/commandline.h +++ b/3rdparty/bx/include/bx/commandline.h @@ -7,197 +7,64 @@ #define BX_COMMANDLINE_H_HEADER_GUARD #include "bx.h" -#include "string.h" namespace bx { + /// Reference: + /// http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int32_t& _argc, char* _argv[], int32_t _maxArgvs, char _term = '\0'); + + /// class CommandLine { public: - CommandLine(int _argc, char const* const* _argv) - : m_argc(_argc) - , m_argv(_argv) - { - } - - const char* findOption(const char* _long, const char* _default) const - { - const char* result = find(0, '\0', _long, 1); - return result == NULL ? _default : result; - } - - const char* findOption(const char _short, const char* _long, const char* _default) const - { - const char* result = find(0, _short, _long, 1); - return result == NULL ? _default : result; - } - - const char* findOption(const char* _long, int _numParams = 1) const - { - const char* result = find(0, '\0', _long, _numParams); - return result; - } - - const char* findOption(const char _short, const char* _long = NULL, int _numParams = 1) const - { - const char* result = find(0, _short, _long, _numParams); - return result; - } - - const char* findOption(int _skip, const char _short, const char* _long = NULL, int _numParams = 1) const - { - const char* result = find(_skip, _short, _long, _numParams); - return result; - } - - bool hasArg(const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 0); - return NULL != arg; - } - - bool hasArg(const char* _long) const - { - const char* arg = findOption('\0', _long, 0); - return NULL != arg; - } - - bool hasArg(const char*& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - _value = arg; - return NULL != arg; - } - - bool hasArg(int& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - if (NULL != arg) - { - _value = atoi(arg); - return true; - } - - return false; - } - - bool hasArg(unsigned int& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - if (NULL != arg) - { - _value = atoi(arg); - return true; - } - - return false; - } - - bool hasArg(float& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - if (NULL != arg) - { - _value = float(atof(arg)); - return true; - } - - return false; - } - - bool hasArg(double& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - if (NULL != arg) - { - _value = atof(arg); - return true; - } - - return false; - } - - bool hasArg(bool& _value, const char _short, const char* _long = NULL) const - { - const char* arg = findOption(_short, _long, 1); - if (NULL != arg) - { - if ('0' == *arg || (0 == stricmp(arg, "false") ) ) - { - _value = false; - } - else if ('0' != *arg || (0 == stricmp(arg, "true") ) ) - { - _value = true; - } - - return true; - } - - return false; - } + /// + CommandLine(int32_t _argc, char const* const* _argv); + + /// + const char* findOption(const char* _long, const char* _default) const; + + /// + const char* findOption(const char _short, const char* _long, const char* _default) const; + + /// + const char* findOption(const char* _long, int32_t _numParams = 1) const; + + /// + const char* findOption(const char _short, const char* _long = NULL, int32_t _numParams = 1) const; + + /// + const char* findOption(int32_t _skip, const char _short, const char* _long = NULL, int32_t _numParams = 1) const; + + /// + bool hasArg(const char _short, const char* _long = NULL) const; + + /// + bool hasArg(const char* _long) const; + + /// + bool hasArg(const char*& _value, const char _short, const char* _long = NULL) const; + + /// + bool hasArg(int32_t& _value, const char _short, const char* _long = NULL) const; + + /// + bool hasArg(uint32_t& _value, const char _short, const char* _long = NULL) const; + + /// + bool hasArg(float& _value, const char _short, const char* _long = NULL) const; + + /// + bool hasArg(double& _value, const char _short, const char* _long = NULL) const; + + /// + bool hasArg(bool& _value, const char _short, const char* _long = NULL) const; private: - const char* find(int _skip, const char _short, const char* _long, int _numParams) const - { - for (int ii = 0; ii < m_argc; ++ii) - { - const char* arg = m_argv[ii]; - if ('-' == *arg) - { - ++arg; - if (_short == *arg) - { - if (1 == strlen(arg) ) - { - if (0 == _skip) - { - if (0 == _numParams) - { - return ""; - } - else if (ii+_numParams < m_argc - && '-' != *m_argv[ii+1] ) - { - return m_argv[ii+1]; - } - - return NULL; - } - - --_skip; - ii += _numParams; - } - } - else if (NULL != _long - && '-' == *arg - && 0 == stricmp(arg+1, _long) ) - { - if (0 == _skip) - { - if (0 == _numParams) - { - return ""; - } - else if (ii+_numParams < m_argc - && '-' != *m_argv[ii+1] ) - { - return m_argv[ii+1]; - } - - return NULL; - } - - --_skip; - ii += _numParams; - } - } - } - - return NULL; - } - - int m_argc; + /// + const char* find(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const; + + int32_t m_argc; char const* const* m_argv; }; diff --git a/3rdparty/bx/include/bx/crtimpl.h b/3rdparty/bx/include/bx/crtimpl.h index b2b3d64c95a..8176c6b9185 100644 --- a/3rdparty/bx/include/bx/crtimpl.h +++ b/3rdparty/bx/include/bx/crtimpl.h @@ -9,7 +9,6 @@ #include "bx.h" #if BX_CONFIG_ALLOCATOR_CRT -# include <malloc.h> # include "allocator.h" #endif // BX_CONFIG_ALLOCATOR_CRT @@ -20,374 +19,129 @@ namespace bx { #if BX_CONFIG_ALLOCATOR_CRT + /// class CrtAllocator : public AllocatorI { public: - CrtAllocator() - { - } - - virtual ~CrtAllocator() - { - } - - virtual void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE - { - if (0 == _size) - { - if (NULL != _ptr) - { - if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) - { - ::free(_ptr); - return NULL; - } - -# if BX_COMPILER_MSVC - BX_UNUSED(_file, _line); - _aligned_free(_ptr); -# else - bx::alignedFree(this, _ptr, _align, _file, _line); -# endif // BX_ - } - - return NULL; - } - else if (NULL == _ptr) - { - if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) - { - return ::malloc(_size); - } - -# if BX_COMPILER_MSVC - BX_UNUSED(_file, _line); - return _aligned_malloc(_size, _align); -# else - return bx::alignedAlloc(this, _size, _align, _file, _line); -# endif // BX_ - } - - if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) - { - return ::realloc(_ptr, _size); - } - -# if BX_COMPILER_MSVC - BX_UNUSED(_file, _line); - return _aligned_realloc(_ptr, _size, _align); -# else - return bx::alignedRealloc(this, _ptr, _size, _align, _file, _line); -# endif // BX_ - } + /// + CrtAllocator(); + + /// + virtual ~CrtAllocator(); + + /// + virtual void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE; }; #endif // BX_CONFIG_ALLOCATOR_CRT #if BX_CONFIG_CRT_FILE_READER_WRITER - -# if BX_CRT_MSVC -# define fseeko64 _fseeki64 -# define ftello64 _ftelli64 -# elif 0 \ - || BX_PLATFORM_ANDROID \ - || BX_PLATFORM_BSD \ - || BX_PLATFORM_IOS \ - || BX_PLATFORM_OSX \ - || BX_PLATFORM_QNX -# define fseeko64 fseeko -# define ftello64 ftello -# elif BX_PLATFORM_PS4 -# define fseeko64 fseek -# define ftello64 ftell -# endif // BX_ - + /// class CrtFileReader : public FileReaderI { public: - CrtFileReader() - : m_file(NULL) - { - } - - virtual ~CrtFileReader() - { - } - - virtual bool open(const char* _filePath, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - if (NULL != m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "CrtFileReader: File is already open."); - return false; - } - - m_file = fopen(_filePath, "rb"); - if (NULL == m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "CrtFileReader: Failed to open file."); - return false; - } - - return true; - } - - virtual void close() BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - fclose(m_file); - m_file = NULL; - } - - virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - fseeko64(m_file, _offset, _whence); - return ftello64(m_file); - } - - virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - int32_t size = (int32_t)fread(_data, 1, _size, m_file); - if (size != _size) - { - if (0 != feof(m_file) ) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "CrtFileReader: EOF."); - } - else if (0 != ferror(m_file) ) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "CrtFileReader: read error."); - } - - return size >= 0 ? size : 0; - } - - return size; - } + /// + CrtFileReader(); + + /// + virtual ~CrtFileReader(); + + /// + virtual bool open(const char* _filePath, Error* _err) BX_OVERRIDE; + + /// + virtual void close() BX_OVERRIDE; + + /// + virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE; + + /// + virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE; private: - FILE* m_file; + void* m_file; }; + /// class CrtFileWriter : public FileWriterI { public: - CrtFileWriter() - : m_file(NULL) - { - } - - virtual ~CrtFileWriter() - { - } - - virtual bool open(const char* _filePath, bool _append, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - if (NULL != m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "CrtFileReader: File is already open."); - return false; - } - - m_file = fopen(_filePath, _append ? "ab" : "wb"); - - if (NULL == m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "CrtFileWriter: Failed to open file."); - return false; - } - - return true; - } - - virtual void close() BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - fclose(m_file); - m_file = NULL; - } - - virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - fseeko64(m_file, _offset, _whence); - return ftello64(m_file); - } - - virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - int32_t size = (int32_t)fwrite(_data, 1, _size, m_file); - if (size != _size) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "CrtFileWriter: write failed."); - return size >= 0 ? size : 0; - } - - return size; - } + /// + CrtFileWriter(); + + /// + virtual ~CrtFileWriter(); + + /// + virtual bool open(const char* _filePath, bool _append, Error* _err) BX_OVERRIDE; + + /// + virtual void close() BX_OVERRIDE; + + /// + virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE; + + /// + virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE; private: - FILE* m_file; + void* m_file; }; #endif // BX_CONFIG_CRT_FILE_READER_WRITER #if BX_CONFIG_CRT_PROCESS - -#if BX_CRT_MSVC -# define popen _popen -# define pclose _pclose -#endif // BX_CRT_MSVC - + /// class ProcessReader : public ReaderOpenI, public CloserI, public ReaderI { public: - ProcessReader() - : m_file(NULL) - { - } - - ~ProcessReader() - { - BX_CHECK(NULL == m_file, "Process not closed!"); - } - - virtual bool open(const char* _command, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - if (NULL != m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessReader: File is already open."); - return false; - } - - m_file = popen(_command, "r"); - if (NULL == m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessReader: Failed to open process."); - return false; - } - - return true; - } - - virtual void close() BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Process not open!"); - m_exitCode = pclose(m_file); - m_file = NULL; - } - - virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); - - int32_t size = (int32_t)fread(_data, 1, _size, m_file); - if (size != _size) - { - if (0 != feof(m_file) ) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "ProcessReader: EOF."); - } - else if (0 != ferror(m_file) ) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "ProcessReader: read error."); - } - - return size >= 0 ? size : 0; - } - - return size; - } - - int32_t getExitCode() const - { - return m_exitCode; - } + /// + ProcessReader(); + + /// + ~ProcessReader(); + + /// + virtual bool open(const char* _command, Error* _err) BX_OVERRIDE; + + /// + virtual void close() BX_OVERRIDE; + + /// + virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE; + + /// + int32_t getExitCode() const; private: - FILE* m_file; + void* m_file; int32_t m_exitCode; }; + /// class ProcessWriter : public WriterOpenI, public CloserI, public WriterI { public: - ProcessWriter() - : m_file(NULL) - { - } - - ~ProcessWriter() - { - BX_CHECK(NULL == m_file, "Process not closed!"); - } - - virtual bool open(const char* _command, bool, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - if (NULL != m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessWriter: File is already open."); - return false; - } - - m_file = popen(_command, "w"); - if (NULL == m_file) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessWriter: Failed to open process."); - return false; - } - - return true; - } - - virtual void close() BX_OVERRIDE - { - BX_CHECK(NULL != m_file, "Process not open!"); - m_exitCode = pclose(m_file); - m_file = NULL; - } - - virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); - - int32_t size = (int32_t)fwrite(_data, 1, _size, m_file); - if (size != _size) - { - if (0 != ferror(m_file) ) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "ProcessWriter: write error."); - } - - return size >= 0 ? size : 0; - } - - return size; - } - - int32_t getExitCode() const - { - return m_exitCode; - } + /// + ProcessWriter(); + + /// + ~ProcessWriter(); + + /// + virtual bool open(const char* _command, bool, Error* _err) BX_OVERRIDE; + + /// + virtual void close() BX_OVERRIDE; + + /// + virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE; + + /// + int32_t getExitCode() const; private: - FILE* m_file; + void* m_file; int32_t m_exitCode; }; - #endif // BX_CONFIG_CRT_PROCESS } // namespace bx diff --git a/3rdparty/bx/include/bx/debug.h b/3rdparty/bx/include/bx/debug.h index c94f744aad2..641a0ed82bf 100644 --- a/3rdparty/bx/include/bx/debug.h +++ b/3rdparty/bx/include/bx/debug.h @@ -7,69 +7,24 @@ #define BX_DEBUG_H_HEADER_GUARD #include "bx.h" - -#if BX_PLATFORM_ANDROID -# include <android/log.h> -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE -extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str); -#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX -# if defined(__OBJC__) -# import <Foundation/NSObjCRuntime.h> -# else -# include <CoreFoundation/CFString.h> -extern "C" void NSLog(CFStringRef _format, ...); -# endif // defined(__OBJC__) -#elif 0 // BX_PLATFORM_EMSCRIPTEN -# include <emscripten.h> -#else -# include <stdio.h> -#endif // BX_PLATFORM_WINDOWS +#include <stdarg.h> // va_list namespace bx { -#if BX_COMPILER_CLANG_ANALYZER - inline __attribute__((analyzer_noreturn)) void debugBreak(); -#endif // BX_COMPILER_CLANG_ANALYZER + /// + void debugBreak(); + + /// + void debugOutput(const char* _out); + + /// + void debugPrintfVargs(const char* _format, va_list _argList); - inline void debugBreak() - { -#if BX_COMPILER_MSVC - __debugbreak(); -#elif BX_CPU_ARM - __builtin_trap(); -// asm("bkpt 0"); -#elif !BX_PLATFORM_NACL && BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG) - // NaCl doesn't like int 3: - // NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules. - __asm__ ("int $3"); -#else // cross platform implementation - int* int3 = (int*)3L; - *int3 = 3; -#endif // BX - } + /// + void debugPrintf(const char* _format, ...); - inline void debugOutput(const char* _out) - { -#if BX_PLATFORM_ANDROID -# ifndef BX_ANDROID_LOG_TAG -# define BX_ANDROID_LOG_TAG "" -# endif // BX_ANDROID_LOG_TAG - __android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out); -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE - OutputDebugStringA(_out); -#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX -# if defined(__OBJC__) - NSLog(@"%s", _out); -# else - NSLog(__CFStringMakeConstantString("%s"), _out); -# endif // defined(__OBJC__) -#elif 0 // BX_PLATFORM_EMSCRIPTEN - emscripten_log(EM_LOG_CONSOLE, "%s", _out); -#else - fputs(_out, stdout); - fflush(stdout); -#endif // BX_PLATFORM_ - } + /// + void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...); } // namespace bx diff --git a/3rdparty/bx/include/bx/easing.h b/3rdparty/bx/include/bx/easing.h index 3db6eec53a2..9efbc515378 100644 --- a/3rdparty/bx/include/bx/easing.h +++ b/3rdparty/bx/include/bx/easing.h @@ -14,6 +14,7 @@ namespace bx { + /// struct Easing { enum Enum @@ -64,252 +65,134 @@ namespace bx }; }; + /// typedef float (*EaseFn)(float _t); - template<EaseFn ease> - float easeOut(float _t) - { - return 1.0f - ease(1.0f - _t); - } + /// + float easeLinear(float _t); - template<EaseFn easeFrom0toH, EaseFn easeFromHto1> - float easeMix(float _t) - { - return _t < 0.5f - ? easeFrom0toH(2.0f*_t)*0.5f - : easeFromHto1(2.0f*_t - 1.0f)*0.5f + 0.5f - ; - } + /// + float easeInQuad(float _t); - inline float easeLinear(float _t) - { - return _t; - } + /// + float easeOutQuad(float _t); - inline float easeInQuad(float _t) - { - return fsq(_t); - } + /// + float easeInOutQuad(float _t); - inline float easeOutQuad(float _t) - { - return easeOut<easeInQuad>(_t); - } + /// + float easeOutInQuad(float _t); - inline float easeInOutQuad(float _t) - { - return easeMix<easeInQuad, easeOutQuad>(_t); - } + /// + float easeInCubic(float _t); - inline float easeOutInQuad(float _t) - { - return easeMix<easeOutQuad, easeInQuad>(_t); - } + /// + float easeOutCubic(float _t); - inline float easeInCubic(float _t) - { - return _t*_t*_t; - } + /// + float easeInOutCubic(float _t); - inline float easeOutCubic(float _t) - { - return easeOut<easeInCubic>(_t); - } + /// + float easeOutInCubic(float _t); - inline float easeInOutCubic(float _t) - { - return easeMix<easeInCubic, easeOutCubic>(_t); - } + /// + float easeInQuart(float _t); - inline float easeOutInCubic(float _t) - { - return easeMix<easeOutCubic, easeInCubic>(_t); - } + /// + float easeOutQuart(float _t); - inline float easeInQuart(float _t) - { - return _t*_t*_t*_t; - } + /// + float easeInOutQuart(float _t); - inline float easeOutQuart(float _t) - { - return easeOut<easeInQuart>(_t); - } + /// + float easeOutInQuart(float _t); - inline float easeInOutQuart(float _t) - { - return easeMix<easeInQuart, easeOutQuart>(_t); - } - - inline float easeOutInQuart(float _t) - { - return easeMix<easeOutQuart, easeInQuart>(_t); - } - - inline float easeInQuint(float _t) - { - return _t*_t*_t*_t*_t; - } - - inline float easeOutQuint(float _t) - { - return easeOut<easeInQuint>(_t); - } + /// + float easeInQuint(float _t); - inline float easeInOutQuint(float _t) - { - return easeMix<easeInQuint, easeOutQuint>(_t); - } + /// + float easeOutQuint(float _t); - inline float easeOutInQuint(float _t) - { - return easeMix<easeOutQuint, easeInQuint>(_t); - } + /// + float easeInOutQuint(float _t); - inline float easeInSine(float _t) - { - return 1.0f - fcos(_t*piHalf); - } + /// + float easeOutInQuint(float _t); - inline float easeOutSine(float _t) - { - return easeOut<easeInSine>(_t); - } + /// + float easeInSine(float _t); - inline float easeInOutSine(float _t) - { - return easeMix<easeInSine, easeOutSine>(_t); - } + /// + float easeOutSine(float _t); - inline float easeOutInSine(float _t) - { - return easeMix<easeOutSine, easeInSine>(_t); - } + /// + float easeInOutSine(float _t); - inline float easeInExpo(float _t) - { - return fpow(2.0f, 10.0f * (_t - 1.0f) ) - 0.001f; - } + /// + float easeOutInSine(float _t); - inline float easeOutExpo(float _t) - { - return easeOut<easeInExpo>(_t); - } + /// + float easeInExpo(float _t); - inline float easeInOutExpo(float _t) - { - return easeMix<easeInExpo, easeOutExpo>(_t); - } + /// + float easeOutExpo(float _t); - inline float easeOutInExpo(float _t) - { - return easeMix<easeOutExpo, easeInExpo>(_t); - } + /// + float easeInOutExpo(float _t); - inline float easeInCirc(float _t) - { - return -(fsqrt(1.0f - _t*_t) - 1.0f); - } + /// + float easeOutInExpo(float _t); - inline float easeOutCirc(float _t) - { - return easeOut<easeInCirc>(_t); - } + /// + float easeInCirc(float _t); - inline float easeInOutCirc(float _t) - { - return easeMix<easeInCirc, easeOutCirc>(_t); - } + /// + float easeOutCirc(float _t); - inline float easeOutInCirc(float _t) - { - return easeMix<easeOutCirc, easeInCirc>(_t); - } + /// + float easeInOutCirc(float _t); - inline float easeOutElastic(float _t) - { - return fpow(2.0f, -10.0f*_t)*fsin( (_t-0.3f/4.0f)*(2.0f*pi)/0.3f) + 1.0f; - } + /// + float easeOutInCirc(float _t); - inline float easeInElastic(float _t) - { - return easeOut<easeOutElastic>(_t); - } + /// + float easeOutElastic(float _t); - inline float easeInOutElastic(float _t) - { - return easeMix<easeInElastic, easeOutElastic>(_t); - } + /// + float easeInElastic(float _t); - inline float easeOutInElastic(float _t) - { - return easeMix<easeOutElastic, easeInElastic>(_t); - } + /// + float easeInOutElastic(float _t); - inline float easeInBack(float _t) - { - return easeInCubic(_t) - _t*fsin(_t*pi); - } + /// + float easeOutInElastic(float _t); - inline float easeOutBack(float _t) - { - return easeOut<easeInBack>(_t); - } + /// + float easeInBack(float _t); - inline float easeInOutBack(float _t) - { - return easeMix<easeInBack, easeOutBack>(_t); - } + /// + float easeOutBack(float _t); - inline float easeOutInBack(float _t) - { - return easeMix<easeOutBack, easeInBack>(_t); - } + /// + float easeInOutBack(float _t); - inline float easeOutBounce(float _t) - { - if (4.0f/11.0f > _t) - { - return 121.0f/16.0f*_t*_t; - } + /// + float easeOutInBack(float _t); - if (8.0f/11.0f > _t) - { - return 363.0f/40.0f*_t*_t - - 99.0f/10.0f*_t - + 17.0f/ 5.0f - ; - } + /// + float easeOutBounce(float _t); - if (9.0f/10.0f > _t) - { - return 4356.0f/ 361.0f*_t*_t - - 35442.0f/1805.0f*_t - + 16061.0f/1805.0f - ; - } - - return 54.0f/ 5.0f*_t*_t - - 513.0f/25.0f*_t - + 268.0f/25.0f - ; - } - - inline float easeInBounce(float _t) - { - return easeOut<easeOutBounce>(_t); - } + /// + float easeInBounce(float _t); - inline float easeInOutBounce(float _t) - { - return easeMix<easeInBounce, easeOutBounce>(_t); - } + /// + float easeInOutBounce(float _t); - inline float easeOutInBounce(float _t) - { - return easeMix<easeOutBounce, easeInBounce>(_t); - } + /// + float easeOutInBounce(float _t); } // namespace bx +#include "easing.inl" + #endif // BX_EASING_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/easing.inl b/3rdparty/bx/include/bx/easing.inl new file mode 100644 index 00000000000..b23edb1128a --- /dev/null +++ b/3rdparty/bx/include/bx/easing.inl @@ -0,0 +1,256 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_EASING_H_HEADER_GUARD +# error "Must be included from bx/easing.h!" +#endif // BX_EASING_H_HEADER_GUARD + +namespace bx +{ + template<EaseFn ease> + float easeOut(float _t) + { + return 1.0f - ease(1.0f - _t); + } + + template<EaseFn easeFrom0toH, EaseFn easeFromHto1> + float easeMix(float _t) + { + return _t < 0.5f + ? easeFrom0toH(2.0f*_t)*0.5f + : easeFromHto1(2.0f*_t - 1.0f)*0.5f + 0.5f + ; + } + + inline float easeLinear(float _t) + { + return _t; + } + + inline float easeInQuad(float _t) + { + return fsq(_t); + } + + inline float easeOutQuad(float _t) + { + return easeOut<easeInQuad>(_t); + } + + inline float easeInOutQuad(float _t) + { + return easeMix<easeInQuad, easeOutQuad>(_t); + } + + inline float easeOutInQuad(float _t) + { + return easeMix<easeOutQuad, easeInQuad>(_t); + } + + inline float easeInCubic(float _t) + { + return _t*_t*_t; + } + + inline float easeOutCubic(float _t) + { + return easeOut<easeInCubic>(_t); + } + + inline float easeInOutCubic(float _t) + { + return easeMix<easeInCubic, easeOutCubic>(_t); + } + + inline float easeOutInCubic(float _t) + { + return easeMix<easeOutCubic, easeInCubic>(_t); + } + + inline float easeInQuart(float _t) + { + return _t*_t*_t*_t; + } + + inline float easeOutQuart(float _t) + { + return easeOut<easeInQuart>(_t); + } + + inline float easeInOutQuart(float _t) + { + return easeMix<easeInQuart, easeOutQuart>(_t); + } + + inline float easeOutInQuart(float _t) + { + return easeMix<easeOutQuart, easeInQuart>(_t); + } + + inline float easeInQuint(float _t) + { + return _t*_t*_t*_t*_t; + } + + inline float easeOutQuint(float _t) + { + return easeOut<easeInQuint>(_t); + } + + inline float easeInOutQuint(float _t) + { + return easeMix<easeInQuint, easeOutQuint>(_t); + } + + inline float easeOutInQuint(float _t) + { + return easeMix<easeOutQuint, easeInQuint>(_t); + } + + inline float easeInSine(float _t) + { + return 1.0f - fcos(_t*piHalf); + } + + inline float easeOutSine(float _t) + { + return easeOut<easeInSine>(_t); + } + + inline float easeInOutSine(float _t) + { + return easeMix<easeInSine, easeOutSine>(_t); + } + + inline float easeOutInSine(float _t) + { + return easeMix<easeOutSine, easeInSine>(_t); + } + + inline float easeInExpo(float _t) + { + return fpow(2.0f, 10.0f * (_t - 1.0f) ) - 0.001f; + } + + inline float easeOutExpo(float _t) + { + return easeOut<easeInExpo>(_t); + } + + inline float easeInOutExpo(float _t) + { + return easeMix<easeInExpo, easeOutExpo>(_t); + } + + inline float easeOutInExpo(float _t) + { + return easeMix<easeOutExpo, easeInExpo>(_t); + } + + inline float easeInCirc(float _t) + { + return -(fsqrt(1.0f - _t*_t) - 1.0f); + } + + inline float easeOutCirc(float _t) + { + return easeOut<easeInCirc>(_t); + } + + inline float easeInOutCirc(float _t) + { + return easeMix<easeInCirc, easeOutCirc>(_t); + } + + inline float easeOutInCirc(float _t) + { + return easeMix<easeOutCirc, easeInCirc>(_t); + } + + inline float easeOutElastic(float _t) + { + return fpow(2.0f, -10.0f*_t)*fsin( (_t-0.3f/4.0f)*(2.0f*pi)/0.3f) + 1.0f; + } + + inline float easeInElastic(float _t) + { + return easeOut<easeOutElastic>(_t); + } + + inline float easeInOutElastic(float _t) + { + return easeMix<easeInElastic, easeOutElastic>(_t); + } + + inline float easeOutInElastic(float _t) + { + return easeMix<easeOutElastic, easeInElastic>(_t); + } + + inline float easeInBack(float _t) + { + return easeInCubic(_t) - _t*fsin(_t*pi); + } + + inline float easeOutBack(float _t) + { + return easeOut<easeInBack>(_t); + } + + inline float easeInOutBack(float _t) + { + return easeMix<easeInBack, easeOutBack>(_t); + } + + inline float easeOutInBack(float _t) + { + return easeMix<easeOutBack, easeInBack>(_t); + } + + inline float easeOutBounce(float _t) + { + if (4.0f/11.0f > _t) + { + return 121.0f/16.0f*_t*_t; + } + + if (8.0f/11.0f > _t) + { + return 363.0f/40.0f*_t*_t + - 99.0f/10.0f*_t + + 17.0f/ 5.0f + ; + } + + if (9.0f/10.0f > _t) + { + return 4356.0f/ 361.0f*_t*_t + - 35442.0f/1805.0f*_t + + 16061.0f/1805.0f + ; + } + + return 54.0f/ 5.0f*_t*_t + - 513.0f/25.0f*_t + + 268.0f/25.0f + ; + } + + inline float easeInBounce(float _t) + { + return easeOut<easeOutBounce>(_t); + } + + inline float easeInOutBounce(float _t) + { + return easeMix<easeInBounce, easeOutBounce>(_t); + } + + inline float easeOutInBounce(float _t) + { + return easeMix<easeOutBounce, easeInBounce>(_t); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/endian.h b/3rdparty/bx/include/bx/endian.h index 23e9a665b63..c687d4fa0f2 100644 --- a/3rdparty/bx/include/bx/endian.h +++ b/3rdparty/bx/include/bx/endian.h @@ -10,78 +10,41 @@ namespace bx { - inline uint16_t endianSwap(uint16_t _in) - { - return (_in>>8) | (_in<<8); - } - - inline uint32_t endianSwap(uint32_t _in) - { - return (_in>>24) | (_in<<24) - | ( (_in&0x00ff0000)>>8) | ( (_in&0x0000ff00)<<8) - ; - } + /// + int16_t endianSwap(int16_t _in); - inline uint64_t endianSwap(uint64_t _in) - { - return (_in>>56) | (_in<<56) - | ( (_in&UINT64_C(0x00ff000000000000) )>>40) | ( (_in&UINT64_C(0x000000000000ff00) )<<40) - | ( (_in&UINT64_C(0x0000ff0000000000) )>>24) | ( (_in&UINT64_C(0x0000000000ff0000) )<<24) - | ( (_in&UINT64_C(0x000000ff00000000) )>>8) | ( (_in&UINT64_C(0x00000000ff000000) )<<8) - ; - } + /// + uint16_t endianSwap(uint16_t _in); - inline int16_t endianSwap(int16_t _in) - { - return (int16_t)endianSwap( (uint16_t)_in); - } + /// + int32_t endianSwap(int32_t _in); - inline int32_t endianSwap(int32_t _in) - { - return (int32_t)endianSwap( (uint32_t)_in); - } + /// + uint32_t endianSwap(uint32_t _in); - inline int64_t endianSwap(int64_t _in) - { - return (int64_t)endianSwap( (uint64_t)_in); - } + /// + int64_t endianSwap(int64_t _in); + + /// + uint64_t endianSwap(uint64_t _in); /// Input argument is encoded as little endian, convert it if neccessary /// depending on host CPU endianess. template <typename Ty> - inline Ty toLittleEndian(const Ty _in) - { -#if BX_CPU_ENDIAN_BIG - return endianSwap(_in); -#else - return _in; -#endif // BX_CPU_ENDIAN_BIG - } + Ty toLittleEndian(const Ty _in); /// Input argument is encoded as big endian, convert it if neccessary /// depending on host CPU endianess. template <typename Ty> - inline Ty toBigEndian(const Ty _in) - { -#if BX_CPU_ENDIAN_LITTLE - return endianSwap(_in); -#else - return _in; -#endif // BX_CPU_ENDIAN_LITTLE - } + Ty toBigEndian(const Ty _in); /// If _littleEndian is true, converts input argument to from little endian /// to host CPU endiness. template <typename Ty> - inline Ty toHostEndian(const Ty _in, bool _fromLittleEndian) - { -#if BX_CPU_ENDIAN_LITTLE - return _fromLittleEndian ? _in : endianSwap(_in); -#else - return _fromLittleEndian ? endianSwap(_in) : _in; -#endif // BX_CPU_ENDIAN_LITTLE - } + Ty toHostEndian(const Ty _in, bool _fromLittleEndian); } // namespace bx +#include "endian.inl" + #endif // BX_ENDIAN_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/endian.inl b/3rdparty/bx/include/bx/endian.inl new file mode 100644 index 00000000000..6ec7572c71c --- /dev/null +++ b/3rdparty/bx/include/bx/endian.inl @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_ENDIAN_H_HEADER_GUARD +# error "Must be included from bx/endian.h!" +#endif // BX_ENDIAN_H_HEADER_GUARD + +namespace bx +{ + inline int16_t endianSwap(int16_t _in) + { + return (int16_t)endianSwap( (uint16_t)_in); + } + + inline uint16_t endianSwap(uint16_t _in) + { + return (_in>>8) | (_in<<8); + } + + inline int32_t endianSwap(int32_t _in) + { + return (int32_t)endianSwap( (uint32_t)_in); + } + + inline uint32_t endianSwap(uint32_t _in) + { + return ( _in >>24) | ( _in <<24) + | ( (_in&0x00ff0000)>> 8) | ( (_in&0x0000ff00)<< 8) + ; + } + + inline int64_t endianSwap(int64_t _in) + { + return (int64_t)endianSwap( (uint64_t)_in); + } + + inline uint64_t endianSwap(uint64_t _in) + { + return (_in >>56) | ( _in <<56) + | ( (_in&UINT64_C(0x00ff000000000000) )>>40) | ( (_in&UINT64_C(0x000000000000ff00) )<<40) + | ( (_in&UINT64_C(0x0000ff0000000000) )>>24) | ( (_in&UINT64_C(0x0000000000ff0000) )<<24) + | ( (_in&UINT64_C(0x000000ff00000000) )>> 8) | ( (_in&UINT64_C(0x00000000ff000000) )<< 8) + ; + } + + template <typename Ty> + inline Ty toLittleEndian(const Ty _in) + { +#if BX_CPU_ENDIAN_BIG + return endianSwap(_in); +#else + return _in; +#endif // BX_CPU_ENDIAN_BIG + } + + template <typename Ty> + inline Ty toBigEndian(const Ty _in) + { +#if BX_CPU_ENDIAN_LITTLE + return endianSwap(_in); +#else + return _in; +#endif // BX_CPU_ENDIAN_LITTLE + } + + template <typename Ty> + inline Ty toHostEndian(const Ty _in, bool _fromLittleEndian) + { +#if BX_CPU_ENDIAN_LITTLE + return _fromLittleEndian ? _in : endianSwap(_in); +#else + return _fromLittleEndian ? endianSwap(_in) : _in; +#endif // BX_CPU_ENDIAN_LITTLE + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/error.h b/3rdparty/bx/include/bx/error.h index 598d5689c6c..72a8444342c 100644 --- a/3rdparty/bx/include/bx/error.h +++ b/3rdparty/bx/include/bx/error.h @@ -44,55 +44,29 @@ namespace bx ); public: - Error() - : m_code(0) - { - } - - void reset() - { - m_code = 0; - m_msg.clear(); - } - - void setError(ErrorResult _errorResult, const StringView& _msg) - { - BX_CHECK(0 != _errorResult.code, "Invalid ErrorResult passed to setError!"); - - if (!isOk() ) - { - return; - } - - m_code = _errorResult.code; - m_msg = _msg; - } - - bool isOk() const - { - return 0 == m_code; - } - - ErrorResult get() const - { - ErrorResult result = { m_code }; - return result; - } - - const StringView& getMessage() const - { - return m_msg; - } - - bool operator==(const ErrorResult& _rhs) const - { - return _rhs.code == m_code; - } - - bool operator!=(const ErrorResult& _rhs) const - { - return _rhs.code != m_code; - } + /// + Error(); + + /// + void reset(); + + /// + void setError(ErrorResult _errorResult, const StringView& _msg); + + /// + bool isOk() const; + + /// + ErrorResult get() const; + + /// + const StringView& getMessage() const; + + /// + bool operator==(const ErrorResult& _rhs) const; + + /// + bool operator!=(const ErrorResult& _rhs) const; private: StringView m_msg; @@ -108,16 +82,11 @@ namespace bx ); public: - ErrorScope(Error* _err) - : m_err(_err) - { - BX_CHECK(NULL != _err, "_err can't be NULL"); - } + /// + ErrorScope(Error* _err); - ~ErrorScope() - { - BX_CHECK(m_err->isOk(), "Error: %d", m_err->get().code); - } + /// + ~ErrorScope(); private: Error* m_err; @@ -125,4 +94,6 @@ namespace bx } // namespace bx +#include "error.inl" + #endif // BX_ERROR_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/error.inl b/3rdparty/bx/include/bx/error.inl new file mode 100644 index 00000000000..ac16c6f9841 --- /dev/null +++ b/3rdparty/bx/include/bx/error.inl @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_ERROR_H_HEADER_GUARD +# error "Must be included from bx/error!" +#endif // BX_ERROR_H_HEADER_GUARD + +namespace bx +{ + inline Error::Error() + : m_code(0) + { + } + + inline void Error::reset() + { + m_code = 0; + m_msg.clear(); + } + + inline void Error::setError(ErrorResult _errorResult, const StringView& _msg) + { + BX_CHECK(0 != _errorResult.code, "Invalid ErrorResult passed to setError!"); + + if (!isOk() ) + { + return; + } + + m_code = _errorResult.code; + m_msg = _msg; + } + + inline bool Error::isOk() const + { + return 0 == m_code; + } + + inline ErrorResult Error::get() const + { + ErrorResult result = { m_code }; + return result; + } + + inline const StringView& Error::getMessage() const + { + return m_msg; + } + + inline bool Error::operator==(const ErrorResult& _rhs) const + { + return _rhs.code == m_code; + } + + inline bool Error::operator!=(const ErrorResult& _rhs) const + { + return _rhs.code != m_code; + } + + inline ErrorScope::ErrorScope(Error* _err) + : m_err(_err) + { + BX_CHECK(NULL != _err, "_err can't be NULL"); + } + + inline ErrorScope::~ErrorScope() + { + BX_CHECK(m_err->isOk(), "Error: %d", m_err->get().code); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/foreach.h b/3rdparty/bx/include/bx/foreach.h deleted file mode 100644 index 53a6dde7265..00000000000 --- a/3rdparty/bx/include/bx/foreach.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2010-2017 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause - */ - -#ifndef BX_FOREACH_H_HEADER_GUARD -#define BX_FOREACH_H_HEADER_GUARD - -#include "bx.h" - -namespace bx -{ - namespace foreach_ns - { - struct ContainerBase - { - }; - - template <typename Ty> - class Container : public ContainerBase - { - public: - inline Container(const Ty& _container) - : m_container(_container) - , m_break(0) - , m_it( _container.begin() ) - , m_itEnd( _container.end() ) - { - } - - inline bool condition() const - { - return (!m_break++ && m_it != m_itEnd); - } - - const Ty& m_container; - mutable int m_break; - mutable typename Ty::const_iterator m_it; - mutable typename Ty::const_iterator m_itEnd; - }; - - template <typename Ty> - inline Ty* pointer(const Ty&) - { - return 0; - } - - template <typename Ty> - inline Container<Ty> containerNew(const Ty& _container) - { - return Container<Ty>(_container); - } - - template <typename Ty> - inline const Container<Ty>* container(const ContainerBase* _base, const Ty*) - { - return static_cast<const Container<Ty>*>(_base); - } - } // namespace foreach_ns - -#define foreach(_variable, _container) \ - for (const bx::foreach_ns::ContainerBase &__temp_container__ = bx::foreach_ns::containerNew(_container); \ - bx::foreach_ns::container(&__temp_container__, true ? 0 : bx::foreach_ns::pointer(_container) )->condition(); \ - ++bx::foreach_ns::container(&__temp_container__, true ? 0 : bx::foreach_ns::pointer(_container) )->m_it) \ - for (_variable = *container(&__temp_container__, true ? 0 : bx::foreach_ns::pointer(_container) )->m_it; \ - bx::foreach_ns::container(&__temp_container__, true ? 0 : bx::foreach_ns::pointer(_container) )->m_break; \ - --bx::foreach_ns::container(&__temp_container__, true ? 0 : bx::foreach_ns::pointer(_container) )->m_break) - -} // namespace bx - -#endif // BX_FOREACH_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/fpumath.h b/3rdparty/bx/include/bx/fpumath.h index c7438eb3105..4c04eb6dc52 100644 --- a/3rdparty/bx/include/bx/fpumath.h +++ b/3rdparty/bx/include/bx/fpumath.h @@ -14,11 +14,13 @@ namespace bx { - static const float pi = 3.14159265358979323846f; - static const float invPi = 1.0f/3.14159265358979323846f; - static const float piHalf = 1.57079632679489661923f; - static const float sqrt2 = 1.41421356237309504880f; + extern const float pi; + extern const float invPi; + extern const float piHalf; + extern const float sqrt2; + extern const float huge; + /// struct Handness { enum Enum @@ -28,6 +30,7 @@ namespace bx }; }; + /// struct NearFar { enum Enum @@ -37,1425 +40,436 @@ namespace bx }; }; - inline float toRad(float _deg) - { - return _deg * pi / 180.0f; - } - - inline float toDeg(float _rad) - { - return _rad * 180.0f / pi; - } - - inline float ffloor(float _f) - { - return floorf(_f); - } - - inline float fceil(float _f) - { - return ceilf(_f); - } - - inline float fround(float _f) - { - return ffloor(_f + 0.5f); - } - - inline float fmin(float _a, float _b) - { - return _a < _b ? _a : _b; - } + /// + float toRad(float _deg); - inline float fmax(float _a, float _b) - { - return _a > _b ? _a : _b; - } + /// + float toDeg(float _rad); - inline float fmin3(float _a, float _b, float _c) - { - return fmin(_a, fmin(_b, _c) ); - } + /// + uint32_t floatToBits(float _a); - inline float fmax3(float _a, float _b, float _c) - { - return fmax(_a, fmax(_b, _c) ); - } + /// + float bitsToFloat(uint32_t _a); - inline float fclamp(float _a, float _min, float _max) - { - return fmin(fmax(_a, _min), _max); - } + /// + uint64_t doubleToBits(double _a); - inline float fsaturate(float _a) - { - return fclamp(_a, 0.0f, 1.0f); - } + /// + double bitsToDouble(uint64_t _a); - inline float flerp(float _a, float _b, float _t) - { - return _a + (_b - _a) * _t; - } + /// + bool isNan(float _f); - inline float fsign(float _a) - { - return _a < 0.0f ? -1.0f : 1.0f; - } + /// + bool isNan(double _f); - inline float fabsolute(float _a) - { - return fabsf(_a); - } + /// + bool isFinite(float _f); - inline float fsq(float _a) - { - return _a * _a; - } - - inline float fsin(float _a) - { - return sinf(_a); - } + /// + bool isFinite(double _f); - inline float fasin(float _a) - { - return asinf(_a); - } + /// + bool isInfinite(float _f); - inline float fcos(float _a) - { - return cosf(_a); - } + /// + bool isInfinite(double _f); - inline float facos(float _a) - { - return acosf(_a); - } + /// + float ffloor(float _f); - inline float fpow(float _a, float _b) - { - return powf(_a, _b); - } + /// + float fceil(float _f); - inline float fexp2(float _a) - { - return fpow(2.0f, _a); - } + /// + float fround(float _f); - inline float flog(float _a) - { - return logf(_a); - } + /// + float fmin(float _a, float _b); - inline float flog2(float _a) - { - return flog(_a) * 1.442695041f; - } + /// + float fmax(float _a, float _b); - inline float fsqrt(float _a) - { - return sqrtf(_a); - } + /// + float fmin3(float _a, float _b, float _c); - inline float frsqrt(float _a) - { - return 1.0f/fsqrt(_a); - } + /// + float fmax3(float _a, float _b, float _c); - inline float ffract(float _a) - { - return _a - floorf(_a); - } + /// + float fclamp(float _a, float _min, float _max); - inline float fmod(float _a, float _b) - { - return fmodf(_a, _b); - } + /// + float fsaturate(float _a); - inline bool fequal(float _a, float _b, float _epsilon) - { - // http://realtimecollisiondetection.net/blog/?p=89 - const float lhs = fabsolute(_a - _b); - const float rhs = _epsilon * fmax3(1.0f, fabsolute(_a), fabsolute(_b) ); - return lhs <= rhs; - } + /// + float flerp(float _a, float _b, float _t); - inline bool fequal(const float* __restrict _a, const float* __restrict _b, uint32_t _num, float _epsilon) - { - bool equal = fequal(_a[0], _b[0], _epsilon); - for (uint32_t ii = 1; equal && ii < _num; ++ii) - { - equal = fequal(_a[ii], _b[ii], _epsilon); - } - return equal; - } + /// + float fsign(float _a); - inline float fwrap(float _a, float _wrap) - { - const float mod = fmod(_a, _wrap); - const float result = mod < 0.0f ? _wrap + mod : mod; - return result; - } + /// + float fabsolute(float _a); - inline float fstep(float _edge, float _a) - { - return _a < _edge ? 0.0f : 1.0f; - } + /// + float fsq(float _a); - inline float fpulse(float _a, float _start, float _end) - { - return fstep(_a, _start) - fstep(_a, _end); - } + /// + float fsin(float _a); - inline float fsmoothstep(float _a) - { - return fsq(_a)*(3.0f - 2.0f*_a); - } + /// + float fasin(float _a); - // References: - // - Bias And Gain Are Your Friend - // http://blog.demofox.org/2012/09/24/bias-and-gain-are-your-friend/ - // - http://demofox.org/biasgain.html - inline float fbias(float _time, float _bias) - { - return _time / ( ( (1.0f/_bias - 2.0f)*(1.0f - _time) ) + 1.0f); - } + /// + float fcos(float _a); - inline float fgain(float _time, float _gain) - { - if (_time < 0.5f) - { - return fbias(_time * 2.0f, _gain) * 0.5f; - } + /// + float facos(float _a); - return fbias(_time * 2.0f - 1.0f, 1.0f - _gain) * 0.5f + 0.5f; - } + /// + float fatan2(float _y, float _x); - inline void vec3Move(float* __restrict _result, const float* __restrict _a) - { - _result[0] = _a[0]; - _result[1] = _a[1]; - _result[2] = _a[2]; - } + /// + float fpow(float _a, float _b); - inline void vec3Abs(float* __restrict _result, const float* __restrict _a) - { - _result[0] = fabsolute(_a[0]); - _result[1] = fabsolute(_a[1]); - _result[2] = fabsolute(_a[2]); - } + /// + float fexp2(float _a); - inline void vec3Neg(float* __restrict _result, const float* __restrict _a) - { - _result[0] = -_a[0]; - _result[1] = -_a[1]; - _result[2] = -_a[2]; - } + /// + float flog(float _a); - inline void vec3Add(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = _a[0] + _b[0]; - _result[1] = _a[1] + _b[1]; - _result[2] = _a[2] + _b[2]; - } + /// + float flog2(float _a); - inline void vec3Add(float* __restrict _result, const float* __restrict _a, float _b) - { - _result[0] = _a[0] + _b; - _result[1] = _a[1] + _b; - _result[2] = _a[2] + _b; - } + /// + float fsqrt(float _a); - inline void vec3Sub(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = _a[0] - _b[0]; - _result[1] = _a[1] - _b[1]; - _result[2] = _a[2] - _b[2]; - } + /// + float frsqrt(float _a); - inline void vec3Sub(float* __restrict _result, const float* __restrict _a, float _b) - { - _result[0] = _a[0] - _b; - _result[1] = _a[1] - _b; - _result[2] = _a[2] - _b; - } + /// + float ffract(float _a); - inline void vec3Mul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = _a[0] * _b[0]; - _result[1] = _a[1] * _b[1]; - _result[2] = _a[2] * _b[2]; - } + /// + float fmod(float _a, float _b); - inline void vec3Mul(float* __restrict _result, const float* __restrict _a, float _b) - { - _result[0] = _a[0] * _b; - _result[1] = _a[1] * _b; - _result[2] = _a[2] * _b; - } + /// + bool fequal(float _a, float _b, float _epsilon); - inline float vec3Dot(const float* __restrict _a, const float* __restrict _b) - { - return _a[0]*_b[0] + _a[1]*_b[1] + _a[2]*_b[2]; - } + /// + bool fequal(const float* __restrict _a, const float* __restrict _b, uint32_t _num, float _epsilon); - inline void vec3Cross(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = _a[1]*_b[2] - _a[2]*_b[1]; - _result[1] = _a[2]*_b[0] - _a[0]*_b[2]; - _result[2] = _a[0]*_b[1] - _a[1]*_b[0]; - } + /// + float fwrap(float _a, float _wrap); - inline float vec3Length(const float* _a) - { - return fsqrt(vec3Dot(_a, _a) ); - } + /// + float fstep(float _edge, float _a); - inline void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, float _t) - { - _result[0] = flerp(_a[0], _b[0], _t); - _result[1] = flerp(_a[1], _b[1], _t); - _result[2] = flerp(_a[2], _b[2], _t); - } + /// + float fpulse(float _a, float _start, float _end); - inline void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, const float* __restrict _c) - { - _result[0] = flerp(_a[0], _b[0], _c[0]); - _result[1] = flerp(_a[1], _b[1], _c[1]); - _result[2] = flerp(_a[2], _b[2], _c[2]); - } + /// + float fsmoothstep(float _a); - inline float vec3Norm(float* __restrict _result, const float* __restrict _a) - { - const float len = vec3Length(_a); - const float invLen = 1.0f/len; - _result[0] = _a[0] * invLen; - _result[1] = _a[1] * invLen; - _result[2] = _a[2] * invLen; - return len; - } - - inline void vec3Min(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = fmin(_a[0], _b[0]); - _result[1] = fmin(_a[1], _b[1]); - _result[2] = fmin(_a[2], _b[2]); - } + // References: + // - Bias And Gain Are Your Friend + // http://blog.demofox.org/2012/09/24/bias-and-gain-are-your-friend/ + // - http://demofox.org/biasgain.html + /// + float fbias(float _time, float _bias); - inline void vec3Max(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - _result[0] = fmax(_a[0], _b[0]); - _result[1] = fmax(_a[1], _b[1]); - _result[2] = fmax(_a[2], _b[2]); - } + /// + float fgain(float _time, float _gain); - inline void vec3Rcp(float* __restrict _result, const float* __restrict _a) - { - _result[0] = 1.0f / _a[0]; - _result[1] = 1.0f / _a[1]; - _result[2] = 1.0f / _a[2]; - } + /// + void vec3Move(float* __restrict _result, const float* __restrict _a); - /// Calculate tangent frame from normal. - inline void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b) - { - const float nx = _n[0]; - const float ny = _n[1]; - const float nz = _n[2]; + /// + void vec3Abs(float* __restrict _result, const float* __restrict _a); - if (bx::fabsolute(nx) > bx::fabsolute(nz) ) - { - float invLen = 1.0f / bx::fsqrt(nx*nx + nz*nz); - _t[0] = -nz * invLen; - _t[1] = 0.0f; - _t[2] = nx * invLen; - } - else - { - float invLen = 1.0f / bx::fsqrt(ny*ny + nz*nz); - _t[0] = 0.0f; - _t[1] = nz * invLen; - _t[2] = -ny * invLen; - } + /// + void vec3Neg(float* __restrict _result, const float* __restrict _a); - bx::vec3Cross(_b, _n, _t); - } + /// + void vec3Add(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - /// Calculate tangent frame from normal and angle. - inline void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b, float _angle) - { - vec3TangentFrame(_n, _t, _b); + /// + void vec3Add(float* __restrict _result, const float* __restrict _a, float _b); - const float sa = fsin(_angle); - const float ca = fcos(_angle); + /// + void vec3Sub(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - _t[0] = -sa * _b[0] + ca * _t[0]; - _t[1] = -sa * _b[1] + ca * _t[1]; - _t[2] = -sa * _b[2] + ca * _t[2]; + /// + void vec3Sub(float* __restrict _result, const float* __restrict _a, float _b); - bx::vec3Cross(_b, _n, _t); - } + /// + void vec3Mul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - inline void quatIdentity(float* _result) - { - _result[0] = 0.0f; - _result[1] = 0.0f; - _result[2] = 0.0f; - _result[3] = 1.0f; - } + /// + void vec3Mul(float* __restrict _result, const float* __restrict _a, float _b); - inline void quatMove(float* __restrict _result, const float* __restrict _a) - { - _result[0] = _a[0]; - _result[1] = _a[1]; - _result[2] = _a[2]; - _result[3] = _a[3]; - } + /// + float vec3Dot(const float* __restrict _a, const float* __restrict _b); - inline void quatMulXYZ(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb) - { - const float ax = _qa[0]; - const float ay = _qa[1]; - const float az = _qa[2]; - const float aw = _qa[3]; - - const float bx = _qb[0]; - const float by = _qb[1]; - const float bz = _qb[2]; - const float bw = _qb[3]; - - _result[0] = aw * bx + ax * bw + ay * bz - az * by; - _result[1] = aw * by - ax * bz + ay * bw + az * bx; - _result[2] = aw * bz + ax * by - ay * bx + az * bw; - } - - inline void quatMul(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb) - { - const float ax = _qa[0]; - const float ay = _qa[1]; - const float az = _qa[2]; - const float aw = _qa[3]; - - const float bx = _qb[0]; - const float by = _qb[1]; - const float bz = _qb[2]; - const float bw = _qb[3]; - - _result[0] = aw * bx + ax * bw + ay * bz - az * by; - _result[1] = aw * by - ax * bz + ay * bw + az * bx; - _result[2] = aw * bz + ax * by - ay * bx + az * bw; - _result[3] = aw * bw - ax * bx - ay * by - az * bz; - } - - inline void quatInvert(float* __restrict _result, const float* __restrict _quat) - { - _result[0] = -_quat[0]; - _result[1] = -_quat[1]; - _result[2] = -_quat[2]; - _result[3] = _quat[3]; - } + /// + void vec3Cross(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - inline float quatDot(const float* __restrict _a, const float* __restrict _b) - { - return _a[0]*_b[0] - + _a[1]*_b[1] - + _a[2]*_b[2] - + _a[3]*_b[3] - ; - } - - inline void quatNorm(float* __restrict _result, const float* __restrict _quat) - { - const float norm = quatDot(_quat, _quat); - if (0.0f < norm) - { - const float invNorm = 1.0f / fsqrt(norm); - _result[0] = _quat[0] * invNorm; - _result[1] = _quat[1] * invNorm; - _result[2] = _quat[2] * invNorm; - _result[3] = _quat[3] * invNorm; - } - else - { - quatIdentity(_result); - } - } + /// + float vec3Length(const float* _a); - inline void quatToEuler(float* __restrict _result, const float* __restrict _quat) - { - const float x = _quat[0]; - const float y = _quat[1]; - const float z = _quat[2]; - const float w = _quat[3]; + /// + void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, float _t); - const float yy = y * y; - const float zz = z * z; + /// + void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, const float* __restrict _c); - const float xx = x * x; - _result[0] = atan2f(2.0f * (x * w - y * z), 1.0f - 2.0f * (xx + zz) ); - _result[1] = atan2f(2.0f * (y * w + x * z), 1.0f - 2.0f * (yy + zz) ); - _result[2] = asinf (2.0f * (x * y + z * w) ); - } + /// + float vec3Norm(float* __restrict _result, const float* __restrict _a); - inline void quatRotateAxis(float* __restrict _result, const float* _axis, float _angle) - { - const float ha = _angle * 0.5f; - const float ca = fcos(ha); - const float sa = fsin(ha); - _result[0] = _axis[0] * sa; - _result[1] = _axis[1] * sa; - _result[2] = _axis[2] * sa; - _result[3] = ca; - } - - inline void quatRotateX(float* _result, float _ax) - { - const float hx = _ax * 0.5f; - const float cx = fcos(hx); - const float sx = fsin(hx); - _result[0] = sx; - _result[1] = 0.0f; - _result[2] = 0.0f; - _result[3] = cx; - } - - inline void quatRotateY(float* _result, float _ay) - { - const float hy = _ay * 0.5f; - const float cy = fcos(hy); - const float sy = fsin(hy); - _result[0] = 0.0f; - _result[1] = sy; - _result[2] = 0.0f; - _result[3] = cy; - } - - inline void quatRotateZ(float* _result, float _az) - { - const float hz = _az * 0.5f; - const float cz = fcos(hz); - const float sz = fsin(hz); - _result[0] = 0.0f; - _result[1] = 0.0f; - _result[2] = sz; - _result[3] = cz; - } - - inline void vec3MulQuat(float* __restrict _result, const float* __restrict _vec, const float* __restrict _quat) - { - float tmp0[4]; - quatInvert(tmp0, _quat); + /// + void vec3Min(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - float qv[4]; - qv[0] = _vec[0]; - qv[1] = _vec[1]; - qv[2] = _vec[2]; - qv[3] = 0.0f; + /// + void vec3Max(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - float tmp1[4]; - quatMul(tmp1, tmp0, qv); + /// + void vec3Rcp(float* __restrict _result, const float* __restrict _a); - quatMulXYZ(_result, tmp1, _quat); - } + /// Calculate tangent frame from normal. + /// + void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b); - inline void mtxIdentity(float* _result) - { - memset(_result, 0, sizeof(float)*16); - _result[0] = _result[5] = _result[10] = _result[15] = 1.0f; - } + /// Calculate tangent frame from normal and angle. + /// + void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b, float _angle); - inline void mtxTranslate(float* _result, float _tx, float _ty, float _tz) - { - mtxIdentity(_result); - _result[12] = _tx; - _result[13] = _ty; - _result[14] = _tz; - } + /// + void quatIdentity(float* _result); - inline void mtxScale(float* _result, float _sx, float _sy, float _sz) - { - memset(_result, 0, sizeof(float) * 16); - _result[0] = _sx; - _result[5] = _sy; - _result[10] = _sz; - _result[15] = 1.0f; - } - - inline void mtxScale(float* _result, float _scale) - { - mtxScale(_result, _scale, _scale, _scale); - } + /// + void quatMove(float* __restrict _result, const float* __restrict _a); - inline void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos) - { - float tangent[3]; - float bitangent[3]; - vec3TangentFrame(_normal, tangent, bitangent); - - vec3Mul(&_result[ 0], bitangent, _scale); - vec3Mul(&_result[ 4], _normal, _scale); - vec3Mul(&_result[ 8], tangent, _scale); - - _result[ 3] = 0.0f; - _result[ 7] = 0.0f; - _result[11] = 0.0f; - _result[12] = _pos[0]; - _result[13] = _pos[1]; - _result[14] = _pos[2]; - _result[15] = 1.0f; - } - - inline void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos, float _angle) - { - float tangent[3]; - float bitangent[3]; - vec3TangentFrame(_normal, tangent, bitangent, _angle); - - vec3Mul(&_result[ 0], bitangent, _scale); - vec3Mul(&_result[ 4], _normal, _scale); - vec3Mul(&_result[ 8], tangent, _scale); - - _result[ 3] = 0.0f; - _result[ 7] = 0.0f; - _result[11] = 0.0f; - _result[12] = _pos[0]; - _result[13] = _pos[1]; - _result[14] = _pos[2]; - _result[15] = 1.0f; - } - - inline void mtxQuat(float* __restrict _result, const float* __restrict _quat) - { - const float x = _quat[0]; - const float y = _quat[1]; - const float z = _quat[2]; - const float w = _quat[3]; - - const float x2 = x + x; - const float y2 = y + y; - const float z2 = z + z; - const float x2x = x2 * x; - const float x2y = x2 * y; - const float x2z = x2 * z; - const float x2w = x2 * w; - const float y2y = y2 * y; - const float y2z = y2 * z; - const float y2w = y2 * w; - const float z2z = z2 * z; - const float z2w = z2 * w; - - _result[ 0] = 1.0f - (y2y + z2z); - _result[ 1] = x2y - z2w; - _result[ 2] = x2z + y2w; - _result[ 3] = 0.0f; - - _result[ 4] = x2y + z2w; - _result[ 5] = 1.0f - (x2x + z2z); - _result[ 6] = y2z - x2w; - _result[ 7] = 0.0f; - - _result[ 8] = x2z - y2w; - _result[ 9] = y2z + x2w; - _result[10] = 1.0f - (x2x + y2y); - _result[11] = 0.0f; - - _result[12] = 0.0f; - _result[13] = 0.0f; - _result[14] = 0.0f; - _result[15] = 1.0f; - } - - inline void mtxQuatTranslation(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation) - { - mtxQuat(_result, _quat); - _result[12] = -(_result[0]*_translation[0] + _result[4]*_translation[1] + _result[ 8]*_translation[2]); - _result[13] = -(_result[1]*_translation[0] + _result[5]*_translation[1] + _result[ 9]*_translation[2]); - _result[14] = -(_result[2]*_translation[0] + _result[6]*_translation[1] + _result[10]*_translation[2]); - } + /// + void quatMulXYZ(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb); - inline void mtxQuatTranslationHMD(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation) - { - float quat[4]; - quat[0] = -_quat[0]; - quat[1] = -_quat[1]; - quat[2] = _quat[2]; - quat[3] = _quat[3]; - mtxQuatTranslation(_result, quat, _translation); - } - - inline void mtxLookAt_Impl(float* __restrict _result, const float* __restrict _eye, const float* __restrict _view, const float* __restrict _up = NULL) - { - float up[3] = { 0.0f, 1.0f, 0.0f }; - if (NULL != _up) - { - up[0] = _up[0]; - up[1] = _up[1]; - up[2] = _up[2]; - } + /// + void quatMul(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb); - float tmp[4]; - vec3Cross(tmp, up, _view); + /// + void quatInvert(float* __restrict _result, const float* __restrict _quat); - float right[4]; - vec3Norm(right, tmp); + /// + float quatDot(const float* __restrict _a, const float* __restrict _b); - vec3Cross(up, _view, right); + /// + void quatNorm(float* __restrict _result, const float* __restrict _quat); - memset(_result, 0, sizeof(float)*16); - _result[ 0] = right[0]; - _result[ 1] = up[0]; - _result[ 2] = _view[0]; + /// + void quatToEuler(float* __restrict _result, const float* __restrict _quat); - _result[ 4] = right[1]; - _result[ 5] = up[1]; - _result[ 6] = _view[1]; + /// + void quatRotateAxis(float* __restrict _result, const float* _axis, float _angle); - _result[ 8] = right[2]; - _result[ 9] = up[2]; - _result[10] = _view[2]; + /// + void quatRotateX(float* _result, float _ax); - _result[12] = -vec3Dot(right, _eye); - _result[13] = -vec3Dot(up, _eye); - _result[14] = -vec3Dot(_view, _eye); - _result[15] = 1.0f; - } + /// + void quatRotateY(float* _result, float _ay); - inline void mtxLookAtLh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL) - { - float tmp[4]; - vec3Sub(tmp, _at, _eye); + /// + void quatRotateZ(float* _result, float _az); - float view[4]; - vec3Norm(view, tmp); + /// + void vec3MulQuat(float* __restrict _result, const float* __restrict _vec, const float* __restrict _quat); - mtxLookAt_Impl(_result, _eye, view, _up); - } + /// + void mtxIdentity(float* _result); - inline void mtxLookAtRh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL) - { - float tmp[4]; - vec3Sub(tmp, _eye, _at); + /// + void mtxTranslate(float* _result, float _tx, float _ty, float _tz); - float view[4]; - vec3Norm(view, tmp); + /// + void mtxScale(float* _result, float _sx, float _sy, float _sz); - mtxLookAt_Impl(_result, _eye, view, _up); - } + /// + void mtxScale(float* _result, float _scale); - inline void mtxLookAt(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL) - { - mtxLookAtLh(_result, _eye, _at, _up); - } + /// + void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos); - template <Handness::Enum HandnessT> - inline void mtxProjXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, float _far, bool _oglNdc = false) - { - const float diff = _far-_near; - const float aa = _oglNdc ? (_far+_near)/diff : _far/diff; - const float bb = _oglNdc ? (2.0f*_far*_near)/diff : _near*aa; - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = _width; - _result[ 5] = _height; - _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; - _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; - _result[10] = (Handness::Right == HandnessT) ? -aa : aa; - _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; - _result[14] = -bb; - } - - template <Handness::Enum HandnessT> - inline void mtxProj_impl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false) - { - const float invDiffRl = 1.0f/(_rt - _lt); - const float invDiffUd = 1.0f/(_ut - _dt); - const float width = 2.0f*_near * invDiffRl; - const float height = 2.0f*_near * invDiffUd; - const float xx = (_rt + _lt) * invDiffRl; - const float yy = (_ut + _dt) * invDiffUd; - mtxProjXYWH<HandnessT>(_result, xx, yy, width, height, _near, _far, _oglNdc); - } - - template <Handness::Enum HandnessT> - inline void mtxProj_impl(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _far, _oglNdc); - } + /// + void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos, float _angle); - template <Handness::Enum HandnessT> - inline void mtxProj_impl(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false) - { - const float height = 1.0f/tanf(toRad(_fovy)*0.5f); - const float width = height * 1.0f/_aspect; - mtxProjXYWH<HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _far, _oglNdc); - } + /// + void mtxQuat(float* __restrict _result, const float* __restrict _quat); - inline void mtxProj(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } + /// + void mtxQuatTranslation(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation); - inline void mtxProj(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); - } + /// + void mtxQuatTranslationHMD(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation); - inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } + /// + void mtxLookAtLh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL);; - inline void mtxProjLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } + /// + void mtxLookAtRh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL); - inline void mtxProjLh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); - } + /// + void mtxLookAt(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up = NULL); - inline void mtxProjLh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } + /// + void mtxProj(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false); - inline void mtxProjRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); - } + /// + void mtxProj(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false); - inline void mtxProjRh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Right>(_result, _fov, _near, _far, _oglNdc); - } + /// + void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false); - inline void mtxProjRh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false) - { - mtxProj_impl<Handness::Right>(_result, _fovy, _aspect, _near, _far, _oglNdc); - } + /// + void mtxProjLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false); - template <NearFar::Enum NearFarT, Handness::Enum HandnessT> - inline void mtxProjInfXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, bool _oglNdc = false) - { - float aa; - float bb; - if (BX_ENABLED(NearFar::Reverse == NearFarT) ) - { - aa = _oglNdc ? -1.0f : 0.0f; - bb = _oglNdc ? -2.0f*_near : -_near; - } - else - { - aa = 1.0f; - bb = _oglNdc ? 2.0f*_near : _near; - } - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = _width; - _result[ 5] = _height; - _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; - _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; - _result[10] = (Handness::Right == HandnessT) ? -aa : aa; - _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; - _result[14] = -bb; - } - - template <NearFar::Enum NearFarT, Handness::Enum HandnessT> - inline void mtxProjInf_impl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - const float invDiffRl = 1.0f/(_rt - _lt); - const float invDiffUd = 1.0f/(_ut - _dt); - const float width = 2.0f*_near * invDiffRl; - const float height = 2.0f*_near * invDiffUd; - const float xx = (_rt + _lt) * invDiffRl; - const float yy = (_ut + _dt) * invDiffUd; - mtxProjInfXYWH<NearFarT,HandnessT>(_result, xx, yy, width, height, _near, _oglNdc); - } - - template <NearFar::Enum NearFarT, Handness::Enum HandnessT> - inline void mtxProjInf_impl(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFarT,HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _oglNdc); - } + /// + void mtxProjLh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false); - template <NearFar::Enum NearFarT, Handness::Enum HandnessT> - inline void mtxProjInf_impl(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - const float height = 1.0f/tanf(toRad(_fovy)*0.5f); - const float width = height * 1.0f/_aspect; - mtxProjInfXYWH<NearFarT,HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _oglNdc); - } + /// + void mtxProjLh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false); - inline void mtxProjInf(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); - } + /// + void mtxProjRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc = false); - inline void mtxProjInf(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } + /// + void mtxProjRh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc = false); - inline void mtxProjInf(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); - } + /// + void mtxProjRh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc = false); - inline void mtxProjInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } + /// + void mtxProjInf(float* _result, const float _fov[4], float _near, bool _oglNdc = false); - inline void mtxProjInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); - } + /// + void mtxProjInf(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false); - inline void mtxProjInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); - } + /// + void mtxProjInf(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false); - inline void mtxProjInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } + /// + void mtxProjInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false); - inline void mtxProjInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _fov, _near, _oglNdc); - } + /// + void mtxProjInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc = false); - inline void mtxProjInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); - } + /// + void mtxProjInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false); - inline void mtxProjRevInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } + /// + void mtxProjInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false); - inline void mtxProjRevInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _fov, _near, _oglNdc); - } + /// + void mtxProjInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc = false); - inline void mtxProjRevInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); - } + /// + void mtxProjInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false); - inline void mtxProjRevInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); - } + /// + void mtxProjRevInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false); - inline void mtxProjRevInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _fov, _near, _oglNdc); - } + /// + void mtxProjRevInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc = false); - inline void mtxProjRevInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false) - { - mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); - } + /// + void mtxProjRevInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false); - template <Handness::Enum HandnessT> - inline void mtxOrtho_impl(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false) - { - const float aa = 2.0f/(_right - _left); - const float bb = 2.0f/(_top - _bottom); - const float cc = (_oglNdc ? 2.0f : 1.0f) / (_far - _near); - const float dd = (_left + _right)/(_left - _right); - const float ee = (_top + _bottom)/(_bottom - _top); - const float ff = _oglNdc ? (_near + _far)/(_near - _far) : _near/(_near - _far); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = aa; - _result[ 5] = bb; - _result[10] = (Handness::Right == HandnessT) ? -cc : cc; - _result[12] = dd + _offset; - _result[13] = ee; - _result[14] = ff; - _result[15] = 1.0f; - } - - inline void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false) - { - mtxOrtho_impl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } + /// + void mtxProjRevInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc = false); - inline void mtxOrthoLh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false) - { - mtxOrtho_impl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } + /// + void mtxProjRevInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc = false); - inline void mtxOrthoRh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false) - { - mtxOrtho_impl<Handness::Right>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); - } + /// + void mtxProjRevInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc = false); - inline void mtxRotateX(float* _result, float _ax) - { - const float sx = fsin(_ax); - const float cx = fcos(_ax); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = 1.0f; - _result[ 5] = cx; - _result[ 6] = -sx; - _result[ 9] = sx; - _result[10] = cx; - _result[15] = 1.0f; - } - - inline void mtxRotateY(float* _result, float _ay) - { - const float sy = fsin(_ay); - const float cy = fcos(_ay); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = cy; - _result[ 2] = sy; - _result[ 5] = 1.0f; - _result[ 8] = -sy; - _result[10] = cy; - _result[15] = 1.0f; - } - - inline void mtxRotateZ(float* _result, float _az) - { - const float sz = fsin(_az); - const float cz = fcos(_az); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = cz; - _result[ 1] = -sz; - _result[ 4] = sz; - _result[ 5] = cz; - _result[10] = 1.0f; - _result[15] = 1.0f; - } - - inline void mtxRotateXY(float* _result, float _ax, float _ay) - { - const float sx = fsin(_ax); - const float cx = fcos(_ax); - const float sy = fsin(_ay); - const float cy = fcos(_ay); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = cy; - _result[ 2] = sy; - _result[ 4] = sx*sy; - _result[ 5] = cx; - _result[ 6] = -sx*cy; - _result[ 8] = -cx*sy; - _result[ 9] = sx; - _result[10] = cx*cy; - _result[15] = 1.0f; - } - - inline void mtxRotateXYZ(float* _result, float _ax, float _ay, float _az) - { - const float sx = fsin(_ax); - const float cx = fcos(_ax); - const float sy = fsin(_ay); - const float cy = fcos(_ay); - const float sz = fsin(_az); - const float cz = fcos(_az); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = cy*cz; - _result[ 1] = -cy*sz; - _result[ 2] = sy; - _result[ 4] = cz*sx*sy + cx*sz; - _result[ 5] = cx*cz - sx*sy*sz; - _result[ 6] = -cy*sx; - _result[ 8] = -cx*cz*sy + sx*sz; - _result[ 9] = cz*sx + cx*sy*sz; - _result[10] = cx*cy; - _result[15] = 1.0f; - } - - inline void mtxRotateZYX(float* _result, float _ax, float _ay, float _az) - { - const float sx = fsin(_ax); - const float cx = fcos(_ax); - const float sy = fsin(_ay); - const float cy = fcos(_ay); - const float sz = fsin(_az); - const float cz = fcos(_az); - - memset(_result, 0, sizeof(float)*16); - _result[ 0] = cy*cz; - _result[ 1] = cz*sx*sy-cx*sz; - _result[ 2] = cx*cz*sy+sx*sz; - _result[ 4] = cy*sz; - _result[ 5] = cx*cz + sx*sy*sz; - _result[ 6] = -cz*sx + cx*sy*sz; - _result[ 8] = -sy; - _result[ 9] = cy*sx; - _result[10] = cx*cy; - _result[15] = 1.0f; - }; + /// + void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false); - inline void mtxSRT(float* _result, float _sx, float _sy, float _sz, float _ax, float _ay, float _az, float _tx, float _ty, float _tz) - { - const float sx = fsin(_ax); - const float cx = fcos(_ax); - const float sy = fsin(_ay); - const float cy = fcos(_ay); - const float sz = fsin(_az); - const float cz = fcos(_az); - - const float sxsz = sx*sz; - const float cycz = cy*cz; - - _result[ 0] = _sx * (cycz - sxsz*sy); - _result[ 1] = _sx * -cx*sz; - _result[ 2] = _sx * (cz*sy + cy*sxsz); - _result[ 3] = 0.0f; - - _result[ 4] = _sy * (cz*sx*sy + cy*sz); - _result[ 5] = _sy * cx*cz; - _result[ 6] = _sy * (sy*sz -cycz*sx); - _result[ 7] = 0.0f; - - _result[ 8] = _sz * -cx*sy; - _result[ 9] = _sz * sx; - _result[10] = _sz * cx*cy; - _result[11] = 0.0f; - - _result[12] = _tx; - _result[13] = _ty; - _result[14] = _tz; - _result[15] = 1.0f; - } - - inline void vec3MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) - { - _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12]; - _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13]; - _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14]; - } + /// + void mtxOrthoLh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false); - inline void vec3MulMtxH(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) - { - float xx = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12]; - float yy = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13]; - float zz = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14]; - float ww = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _mat[15]; - float invW = fsign(ww)/ww; - _result[0] = xx*invW; - _result[1] = yy*invW; - _result[2] = zz*invW; - } - - inline void vec4MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) - { - _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _vec[3] * _mat[12]; - _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _vec[3] * _mat[13]; - _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _vec[3] * _mat[14]; - _result[3] = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _vec[3] * _mat[15]; - } + /// + void mtxOrthoRh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset = 0.0f, bool _oglNdc = false); - inline void mtxMul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) - { - vec4MulMtx(&_result[ 0], &_a[ 0], _b); - vec4MulMtx(&_result[ 4], &_a[ 4], _b); - vec4MulMtx(&_result[ 8], &_a[ 8], _b); - vec4MulMtx(&_result[12], &_a[12], _b); - } + /// + void mtxRotateX(float* _result, float _ax); - inline void mtxTranspose(float* __restrict _result, const float* __restrict _a) - { - _result[ 0] = _a[ 0]; - _result[ 4] = _a[ 1]; - _result[ 8] = _a[ 2]; - _result[12] = _a[ 3]; - _result[ 1] = _a[ 4]; - _result[ 5] = _a[ 5]; - _result[ 9] = _a[ 6]; - _result[13] = _a[ 7]; - _result[ 2] = _a[ 8]; - _result[ 6] = _a[ 9]; - _result[10] = _a[10]; - _result[14] = _a[11]; - _result[ 3] = _a[12]; - _result[ 7] = _a[13]; - _result[11] = _a[14]; - _result[15] = _a[15]; - } - - inline void mtx3Inverse(float* __restrict _result, const float* __restrict _a) - { - float xx = _a[0]; - float xy = _a[1]; - float xz = _a[2]; - float yx = _a[3]; - float yy = _a[4]; - float yz = _a[5]; - float zx = _a[6]; - float zy = _a[7]; - float zz = _a[8]; - - float det = 0.0f; - det += xx * (yy*zz - yz*zy); - det -= xy * (yx*zz - yz*zx); - det += xz * (yx*zy - yy*zx); - - float invDet = 1.0f/det; - - _result[0] = +(yy*zz - yz*zy) * invDet; - _result[1] = -(xy*zz - xz*zy) * invDet; - _result[2] = +(xy*yz - xz*yy) * invDet; - - _result[3] = -(yx*zz - yz*zx) * invDet; - _result[4] = +(xx*zz - xz*zx) * invDet; - _result[5] = -(xx*yz - xz*yx) * invDet; - - _result[6] = +(yx*zy - yy*zx) * invDet; - _result[7] = -(xx*zy - xy*zx) * invDet; - _result[8] = +(xx*yy - xy*yx) * invDet; - } - - inline void mtxInverse(float* __restrict _result, const float* __restrict _a) - { - float xx = _a[ 0]; - float xy = _a[ 1]; - float xz = _a[ 2]; - float xw = _a[ 3]; - float yx = _a[ 4]; - float yy = _a[ 5]; - float yz = _a[ 6]; - float yw = _a[ 7]; - float zx = _a[ 8]; - float zy = _a[ 9]; - float zz = _a[10]; - float zw = _a[11]; - float wx = _a[12]; - float wy = _a[13]; - float wz = _a[14]; - float ww = _a[15]; - - float det = 0.0f; - det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) ); - det -= xy * (yx*(zz*ww - zw*wz) - yz*(zx*ww - zw*wx) + yw*(zx*wz - zz*wx) ); - det += xz * (yx*(zy*ww - zw*wy) - yy*(zx*ww - zw*wx) + yw*(zx*wy - zy*wx) ); - det -= xw * (yx*(zy*wz - zz*wy) - yy*(zx*wz - zz*wx) + yz*(zx*wy - zy*wx) ); - - float invDet = 1.0f/det; - - _result[ 0] = +(yy*(zz*ww - wz*zw) - yz*(zy*ww - wy*zw) + yw*(zy*wz - wy*zz) ) * invDet; - _result[ 1] = -(xy*(zz*ww - wz*zw) - xz*(zy*ww - wy*zw) + xw*(zy*wz - wy*zz) ) * invDet; - _result[ 2] = +(xy*(yz*ww - wz*yw) - xz*(yy*ww - wy*yw) + xw*(yy*wz - wy*yz) ) * invDet; - _result[ 3] = -(xy*(yz*zw - zz*yw) - xz*(yy*zw - zy*yw) + xw*(yy*zz - zy*yz) ) * invDet; - - _result[ 4] = -(yx*(zz*ww - wz*zw) - yz*(zx*ww - wx*zw) + yw*(zx*wz - wx*zz) ) * invDet; - _result[ 5] = +(xx*(zz*ww - wz*zw) - xz*(zx*ww - wx*zw) + xw*(zx*wz - wx*zz) ) * invDet; - _result[ 6] = -(xx*(yz*ww - wz*yw) - xz*(yx*ww - wx*yw) + xw*(yx*wz - wx*yz) ) * invDet; - _result[ 7] = +(xx*(yz*zw - zz*yw) - xz*(yx*zw - zx*yw) + xw*(yx*zz - zx*yz) ) * invDet; - - _result[ 8] = +(yx*(zy*ww - wy*zw) - yy*(zx*ww - wx*zw) + yw*(zx*wy - wx*zy) ) * invDet; - _result[ 9] = -(xx*(zy*ww - wy*zw) - xy*(zx*ww - wx*zw) + xw*(zx*wy - wx*zy) ) * invDet; - _result[10] = +(xx*(yy*ww - wy*yw) - xy*(yx*ww - wx*yw) + xw*(yx*wy - wx*yy) ) * invDet; - _result[11] = -(xx*(yy*zw - zy*yw) - xy*(yx*zw - zx*yw) + xw*(yx*zy - zx*yy) ) * invDet; - - _result[12] = -(yx*(zy*wz - wy*zz) - yy*(zx*wz - wx*zz) + yz*(zx*wy - wx*zy) ) * invDet; - _result[13] = +(xx*(zy*wz - wy*zz) - xy*(zx*wz - wx*zz) + xz*(zx*wy - wx*zy) ) * invDet; - _result[14] = -(xx*(yy*wz - wy*yz) - xy*(yx*wz - wx*yz) + xz*(yx*wy - wx*yy) ) * invDet; - _result[15] = +(xx*(yy*zz - zy*yz) - xy*(yx*zz - zx*yz) + xz*(yx*zy - zx*yy) ) * invDet; - } + /// + void mtxRotateY(float* _result, float _ay); - /// Convert LH to RH projection matrix and vice versa. - inline void mtxProjFlipHandedness(float* __restrict _dst, const float* __restrict _src) - { - _dst[ 0] = -_src[ 0]; - _dst[ 1] = -_src[ 1]; - _dst[ 2] = -_src[ 2]; - _dst[ 3] = -_src[ 3]; - _dst[ 4] = _src[ 4]; - _dst[ 5] = _src[ 5]; - _dst[ 6] = _src[ 6]; - _dst[ 7] = _src[ 7]; - _dst[ 8] = -_src[ 8]; - _dst[ 9] = -_src[ 9]; - _dst[10] = -_src[10]; - _dst[11] = -_src[11]; - _dst[12] = _src[12]; - _dst[13] = _src[13]; - _dst[14] = _src[14]; - _dst[15] = _src[15]; - } + /// + void mtxRotateZ(float* _result, float _az); - /// Convert LH to RH view matrix and vice versa. - inline void mtxViewFlipHandedness(float* __restrict _dst, const float* __restrict _src) - { - _dst[ 0] = -_src[ 0]; - _dst[ 1] = _src[ 1]; - _dst[ 2] = -_src[ 2]; - _dst[ 3] = _src[ 3]; - _dst[ 4] = -_src[ 4]; - _dst[ 5] = _src[ 5]; - _dst[ 6] = -_src[ 6]; - _dst[ 7] = _src[ 7]; - _dst[ 8] = -_src[ 8]; - _dst[ 9] = _src[ 9]; - _dst[10] = -_src[10]; - _dst[11] = _src[11]; - _dst[12] = -_src[12]; - _dst[13] = _src[13]; - _dst[14] = -_src[14]; - _dst[15] = _src[15]; - } - - inline void calcNormal(float _result[3], float _va[3], float _vb[3], float _vc[3]) - { - float ba[3]; - vec3Sub(ba, _vb, _va); + /// + void mtxRotateXY(float* _result, float _ax, float _ay); - float ca[3]; - vec3Sub(ca, _vc, _va); + /// + void mtxRotateXYZ(float* _result, float _ax, float _ay, float _az); - float baxca[3]; - vec3Cross(baxca, ba, ca); + /// + void mtxRotateZYX(float* _result, float _ax, float _ay, float _az); - vec3Norm(_result, baxca); - } + /// + void mtxSRT(float* _result, float _sx, float _sy, float _sz, float _ax, float _ay, float _az, float _tx, float _ty, float _tz); - inline void calcPlane(float _result[4], float _va[3], float _vb[3], float _vc[3]) - { - float normal[3]; - calcNormal(normal, _va, _vb, _vc); + /// + void vec3MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat); - _result[0] = normal[0]; - _result[1] = normal[1]; - _result[2] = normal[2]; - _result[3] = -vec3Dot(normal, _va); - } + /// + void vec3MulMtxH(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat); - inline void calcLinearFit2D(float _result[2], const void* _points, uint32_t _stride, uint32_t _numPoints) - { - float sumX = 0.0f; - float sumY = 0.0f; - float sumXX = 0.0f; - float sumXY = 0.0f; + /// + void vec4MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat); - const uint8_t* ptr = (const uint8_t*)_points; - for (uint32_t ii = 0; ii < _numPoints; ++ii, ptr += _stride) - { - const float* point = (const float*)ptr; - float xx = point[0]; - float yy = point[1]; - sumX += xx; - sumY += yy; - sumXX += xx*xx; - sumXY += xx*yy; - } - - // [ sum(x^2) sum(x) ] [ A ] = [ sum(x*y) ] - // [ sum(x) numPoints ] [ B ] [ sum(y) ] - - float det = (sumXX*_numPoints - sumX*sumX); - float invDet = 1.0f/det; - - _result[0] = (-sumX * sumY + _numPoints * sumXY) * invDet; - _result[1] = (sumXX * sumY - sumX * sumXY) * invDet; - } - - inline void calcLinearFit3D(float _result[3], const void* _points, uint32_t _stride, uint32_t _numPoints) - { - float sumX = 0.0f; - float sumY = 0.0f; - float sumZ = 0.0f; - float sumXX = 0.0f; - float sumXY = 0.0f; - float sumXZ = 0.0f; - float sumYY = 0.0f; - float sumYZ = 0.0f; - - const uint8_t* ptr = (const uint8_t*)_points; - for (uint32_t ii = 0; ii < _numPoints; ++ii, ptr += _stride) - { - const float* point = (const float*)ptr; - float xx = point[0]; - float yy = point[1]; - float zz = point[2]; - - sumX += xx; - sumY += yy; - sumZ += zz; - sumXX += xx*xx; - sumXY += xx*yy; - sumXZ += xx*zz; - sumYY += yy*yy; - sumYZ += yy*zz; - } - - // [ sum(x^2) sum(x*y) sum(x) ] [ A ] [ sum(x*z) ] - // [ sum(x*y) sum(y^2) sum(y) ] [ B ] = [ sum(y*z) ] - // [ sum(x) sum(y) numPoints ] [ C ] [ sum(z) ] - - float mtx[9] = - { - sumXX, sumXY, sumX, - sumXY, sumYY, sumY, - sumX, sumY, float(_numPoints), - }; - float invMtx[9]; - mtx3Inverse(invMtx, mtx); + /// + void mtxMul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b); - _result[0] = invMtx[0]*sumXZ + invMtx[1]*sumYZ + invMtx[2]*sumZ; - _result[1] = invMtx[3]*sumXZ + invMtx[4]*sumYZ + invMtx[5]*sumZ; - _result[2] = invMtx[6]*sumXZ + invMtx[7]*sumYZ + invMtx[8]*sumZ; - } + /// + void mtxTranspose(float* __restrict _result, const float* __restrict _a); - inline void rgbToHsv(float _hsv[3], const float _rgb[3]) - { - const float rr = _rgb[0]; - const float gg = _rgb[1]; - const float bb = _rgb[2]; + /// + void mtx3Inverse(float* __restrict _result, const float* __restrict _a); - const float s0 = fstep(bb, gg); + /// + void mtxInverse(float* __restrict _result, const float* __restrict _a); - const float px = flerp(bb, gg, s0); - const float py = flerp(gg, bb, s0); - const float pz = flerp(-1.0f, 0.0f, s0); - const float pw = flerp(2.0f/3.0f, -1.0f/3.0f, s0); + /// Convert LH to RH projection matrix and vice versa. + /// + void mtxProjFlipHandedness(float* __restrict _dst, const float* __restrict _src); - const float s1 = fstep(px, rr); + /// Convert LH to RH view matrix and vice versa. + /// + void mtxViewFlipHandedness(float* __restrict _dst, const float* __restrict _src); - const float qx = flerp(px, rr, s1); - const float qy = py; - const float qz = flerp(pw, pz, s1); - const float qw = flerp(rr, px, s1); + /// + void calcNormal(float _result[3], float _va[3], float _vb[3], float _vc[3]); - const float dd = qx - fmin(qw, qy); - const float ee = 1.0e-10f; + /// + void calcPlane(float _result[4], float _va[3], float _vb[3], float _vc[3]); - _hsv[0] = fabsolute(qz + (qw - qy) / (6.0f * dd + ee) ); - _hsv[1] = dd / (qx + ee); - _hsv[2] = qx; - } + /// + void calcLinearFit2D(float _result[2], const void* _points, uint32_t _stride, uint32_t _numPoints); - inline void hsvToRgb(float _rgb[3], const float _hsv[3]) - { - const float hh = _hsv[0]; - const float ss = _hsv[1]; - const float vv = _hsv[2]; + /// + void calcLinearFit3D(float _result[3], const void* _points, uint32_t _stride, uint32_t _numPoints); - const float px = fabsolute(ffract(hh + 1.0f ) * 6.0f - 3.0f); - const float py = fabsolute(ffract(hh + 2.0f/3.0f) * 6.0f - 3.0f); - const float pz = fabsolute(ffract(hh + 1.0f/3.0f) * 6.0f - 3.0f); + /// + void rgbToHsv(float _hsv[3], const float _rgb[3]); - _rgb[0] = vv * flerp(1.0f, fsaturate(px - 1.0f), ss); - _rgb[1] = vv * flerp(1.0f, fsaturate(py - 1.0f), ss); - _rgb[2] = vv * flerp(1.0f, fsaturate(pz - 1.0f), ss); - } + /// + void hsvToRgb(float _rgb[3], const float _hsv[3]); } // namespace bx +#include "fpumath.inl" + #endif // BX_FPU_MATH_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/fpumath.inl b/3rdparty/bx/include/bx/fpumath.inl new file mode 100644 index 00000000000..8a81fc27819 --- /dev/null +++ b/3rdparty/bx/include/bx/fpumath.inl @@ -0,0 +1,1416 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +// FPU math lib + +#ifndef BX_FPU_MATH_H_HEADER_GUARD +# error "Must be included from bx/fpumath.h!" +#endif // BX_FPU_MATH_H_HEADER_GUARD + +#include "bx.h" +#include <math.h> +#include <string.h> + +namespace bx +{ + inline float toRad(float _deg) + { + return _deg * pi / 180.0f; + } + + inline float toDeg(float _rad) + { + return _rad * 180.0f / pi; + } + + inline uint32_t floatToBits(float _a) + { + union { float f; uint32_t ui; } u = { _a }; + return u.ui; + } + + inline float bitsToFloat(uint32_t _a) + { + union { uint32_t ui; float f; } u = { _a }; + return u.f; + } + + inline uint64_t doubleToBits(double _a) + { + union { double f; uint64_t ui; } u = { _a }; + return u.ui; + } + + inline double bitsToDouble(uint64_t _a) + { + union { uint64_t ui; double f; } u = { _a }; + return u.f; + } + + inline bool isNan(float _f) + { + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp > UINT32_C(0x7f800000); + } + + inline bool isNan(double _f) + { + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp > UINT64_C(0x7ff0000000000000); + } + + inline bool isFinite(float _f) + { + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp < UINT32_C(0x7f800000); + } + + inline bool isFinite(double _f) + { + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp < UINT64_C(0x7ff0000000000000); + } + + inline bool isInfinite(float _f) + { + const uint32_t tmp = floatToBits(_f) & INT32_MAX; + return tmp == UINT32_C(0x7f800000); + } + + inline bool isInfinite(double _f) + { + const uint64_t tmp = doubleToBits(_f) & INT64_MAX; + return tmp == UINT64_C(0x7ff0000000000000); + } + + inline float ffloor(float _f) + { + return floorf(_f); + } + + inline float fceil(float _f) + { + return ceilf(_f); + } + + inline float fround(float _f) + { + return ffloor(_f + 0.5f); + } + + inline float fmin(float _a, float _b) + { + return _a < _b ? _a : _b; + } + + inline float fmax(float _a, float _b) + { + return _a > _b ? _a : _b; + } + + inline float fmin3(float _a, float _b, float _c) + { + return fmin(_a, fmin(_b, _c) ); + } + + inline float fmax3(float _a, float _b, float _c) + { + return fmax(_a, fmax(_b, _c) ); + } + + inline float fclamp(float _a, float _min, float _max) + { + return fmin(fmax(_a, _min), _max); + } + + inline float fsaturate(float _a) + { + return fclamp(_a, 0.0f, 1.0f); + } + + inline float flerp(float _a, float _b, float _t) + { + return _a + (_b - _a) * _t; + } + + inline float fsign(float _a) + { + return _a < 0.0f ? -1.0f : 1.0f; + } + + inline float fabsolute(float _a) + { + return fabsf(_a); + } + + inline float fsq(float _a) + { + return _a * _a; + } + + inline float fsin(float _a) + { + return sinf(_a); + } + + inline float fasin(float _a) + { + return asinf(_a); + } + + inline float fcos(float _a) + { + return cosf(_a); + } + + inline float facos(float _a) + { + return acosf(_a); + } + + inline float fatan2(float _y, float _x) + { + return atan2f(_y, _x); + } + + inline float fpow(float _a, float _b) + { + return powf(_a, _b); + } + + inline float fexp2(float _a) + { + return fpow(2.0f, _a); + } + + inline float flog(float _a) + { + return logf(_a); + } + + inline float flog2(float _a) + { + return flog(_a) * 1.442695041f; + } + + inline float fsqrt(float _a) + { + return sqrtf(_a); + } + + inline float frsqrt(float _a) + { + return 1.0f/fsqrt(_a); + } + + inline float ffract(float _a) + { + return _a - floorf(_a); + } + + inline float fmod(float _a, float _b) + { + return fmodf(_a, _b); + } + + inline bool fequal(float _a, float _b, float _epsilon) + { + // http://realtimecollisiondetection.net/blog/?p=89 + const float lhs = fabsolute(_a - _b); + const float rhs = _epsilon * fmax3(1.0f, fabsolute(_a), fabsolute(_b) ); + return lhs <= rhs; + } + + inline bool fequal(const float* __restrict _a, const float* __restrict _b, uint32_t _num, float _epsilon) + { + bool equal = fequal(_a[0], _b[0], _epsilon); + for (uint32_t ii = 1; equal && ii < _num; ++ii) + { + equal = fequal(_a[ii], _b[ii], _epsilon); + } + return equal; + } + + inline float fwrap(float _a, float _wrap) + { + const float mod = fmod(_a, _wrap); + const float result = mod < 0.0f ? _wrap + mod : mod; + return result; + } + + inline float fstep(float _edge, float _a) + { + return _a < _edge ? 0.0f : 1.0f; + } + + inline float fpulse(float _a, float _start, float _end) + { + return fstep(_a, _start) - fstep(_a, _end); + } + + inline float fsmoothstep(float _a) + { + return fsq(_a)*(3.0f - 2.0f*_a); + } + + inline float fbias(float _time, float _bias) + { + return _time / ( ( (1.0f/_bias - 2.0f)*(1.0f - _time) ) + 1.0f); + } + + inline float fgain(float _time, float _gain) + { + if (_time < 0.5f) + { + return fbias(_time * 2.0f, _gain) * 0.5f; + } + + return fbias(_time * 2.0f - 1.0f, 1.0f - _gain) * 0.5f + 0.5f; + } + + inline void vec3Move(float* __restrict _result, const float* __restrict _a) + { + _result[0] = _a[0]; + _result[1] = _a[1]; + _result[2] = _a[2]; + } + + inline void vec3Abs(float* __restrict _result, const float* __restrict _a) + { + _result[0] = fabsolute(_a[0]); + _result[1] = fabsolute(_a[1]); + _result[2] = fabsolute(_a[2]); + } + + inline void vec3Neg(float* __restrict _result, const float* __restrict _a) + { + _result[0] = -_a[0]; + _result[1] = -_a[1]; + _result[2] = -_a[2]; + } + + inline void vec3Add(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = _a[0] + _b[0]; + _result[1] = _a[1] + _b[1]; + _result[2] = _a[2] + _b[2]; + } + + inline void vec3Add(float* __restrict _result, const float* __restrict _a, float _b) + { + _result[0] = _a[0] + _b; + _result[1] = _a[1] + _b; + _result[2] = _a[2] + _b; + } + + inline void vec3Sub(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = _a[0] - _b[0]; + _result[1] = _a[1] - _b[1]; + _result[2] = _a[2] - _b[2]; + } + + inline void vec3Sub(float* __restrict _result, const float* __restrict _a, float _b) + { + _result[0] = _a[0] - _b; + _result[1] = _a[1] - _b; + _result[2] = _a[2] - _b; + } + + inline void vec3Mul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = _a[0] * _b[0]; + _result[1] = _a[1] * _b[1]; + _result[2] = _a[2] * _b[2]; + } + + inline void vec3Mul(float* __restrict _result, const float* __restrict _a, float _b) + { + _result[0] = _a[0] * _b; + _result[1] = _a[1] * _b; + _result[2] = _a[2] * _b; + } + + inline float vec3Dot(const float* __restrict _a, const float* __restrict _b) + { + return _a[0]*_b[0] + _a[1]*_b[1] + _a[2]*_b[2]; + } + + inline void vec3Cross(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = _a[1]*_b[2] - _a[2]*_b[1]; + _result[1] = _a[2]*_b[0] - _a[0]*_b[2]; + _result[2] = _a[0]*_b[1] - _a[1]*_b[0]; + } + + inline float vec3Length(const float* _a) + { + return fsqrt(vec3Dot(_a, _a) ); + } + + inline void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, float _t) + { + _result[0] = flerp(_a[0], _b[0], _t); + _result[1] = flerp(_a[1], _b[1], _t); + _result[2] = flerp(_a[2], _b[2], _t); + } + + inline void vec3Lerp(float* __restrict _result, const float* __restrict _a, const float* __restrict _b, const float* __restrict _c) + { + _result[0] = flerp(_a[0], _b[0], _c[0]); + _result[1] = flerp(_a[1], _b[1], _c[1]); + _result[2] = flerp(_a[2], _b[2], _c[2]); + } + + inline float vec3Norm(float* __restrict _result, const float* __restrict _a) + { + const float len = vec3Length(_a); + const float invLen = 1.0f/len; + _result[0] = _a[0] * invLen; + _result[1] = _a[1] * invLen; + _result[2] = _a[2] * invLen; + return len; + } + + inline void vec3Min(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = fmin(_a[0], _b[0]); + _result[1] = fmin(_a[1], _b[1]); + _result[2] = fmin(_a[2], _b[2]); + } + + inline void vec3Max(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + _result[0] = fmax(_a[0], _b[0]); + _result[1] = fmax(_a[1], _b[1]); + _result[2] = fmax(_a[2], _b[2]); + } + + inline void vec3Rcp(float* __restrict _result, const float* __restrict _a) + { + _result[0] = 1.0f / _a[0]; + _result[1] = 1.0f / _a[1]; + _result[2] = 1.0f / _a[2]; + } + + inline void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b) + { + const float nx = _n[0]; + const float ny = _n[1]; + const float nz = _n[2]; + + if (bx::fabsolute(nx) > bx::fabsolute(nz) ) + { + float invLen = 1.0f / bx::fsqrt(nx*nx + nz*nz); + _t[0] = -nz * invLen; + _t[1] = 0.0f; + _t[2] = nx * invLen; + } + else + { + float invLen = 1.0f / bx::fsqrt(ny*ny + nz*nz); + _t[0] = 0.0f; + _t[1] = nz * invLen; + _t[2] = -ny * invLen; + } + + bx::vec3Cross(_b, _n, _t); + } + + inline void vec3TangentFrame(const float* __restrict _n, float* __restrict _t, float* __restrict _b, float _angle) + { + vec3TangentFrame(_n, _t, _b); + + const float sa = fsin(_angle); + const float ca = fcos(_angle); + + _t[0] = -sa * _b[0] + ca * _t[0]; + _t[1] = -sa * _b[1] + ca * _t[1]; + _t[2] = -sa * _b[2] + ca * _t[2]; + + bx::vec3Cross(_b, _n, _t); + } + + inline void quatIdentity(float* _result) + { + _result[0] = 0.0f; + _result[1] = 0.0f; + _result[2] = 0.0f; + _result[3] = 1.0f; + } + + inline void quatMove(float* __restrict _result, const float* __restrict _a) + { + _result[0] = _a[0]; + _result[1] = _a[1]; + _result[2] = _a[2]; + _result[3] = _a[3]; + } + + inline void quatMulXYZ(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb) + { + const float ax = _qa[0]; + const float ay = _qa[1]; + const float az = _qa[2]; + const float aw = _qa[3]; + + const float bx = _qb[0]; + const float by = _qb[1]; + const float bz = _qb[2]; + const float bw = _qb[3]; + + _result[0] = aw * bx + ax * bw + ay * bz - az * by; + _result[1] = aw * by - ax * bz + ay * bw + az * bx; + _result[2] = aw * bz + ax * by - ay * bx + az * bw; + } + + inline void quatMul(float* __restrict _result, const float* __restrict _qa, const float* __restrict _qb) + { + const float ax = _qa[0]; + const float ay = _qa[1]; + const float az = _qa[2]; + const float aw = _qa[3]; + + const float bx = _qb[0]; + const float by = _qb[1]; + const float bz = _qb[2]; + const float bw = _qb[3]; + + _result[0] = aw * bx + ax * bw + ay * bz - az * by; + _result[1] = aw * by - ax * bz + ay * bw + az * bx; + _result[2] = aw * bz + ax * by - ay * bx + az * bw; + _result[3] = aw * bw - ax * bx - ay * by - az * bz; + } + + inline void quatInvert(float* __restrict _result, const float* __restrict _quat) + { + _result[0] = -_quat[0]; + _result[1] = -_quat[1]; + _result[2] = -_quat[2]; + _result[3] = _quat[3]; + } + + inline float quatDot(const float* __restrict _a, const float* __restrict _b) + { + return _a[0]*_b[0] + + _a[1]*_b[1] + + _a[2]*_b[2] + + _a[3]*_b[3] + ; + } + + inline void quatNorm(float* __restrict _result, const float* __restrict _quat) + { + const float norm = quatDot(_quat, _quat); + if (0.0f < norm) + { + const float invNorm = 1.0f / fsqrt(norm); + _result[0] = _quat[0] * invNorm; + _result[1] = _quat[1] * invNorm; + _result[2] = _quat[2] * invNorm; + _result[3] = _quat[3] * invNorm; + } + else + { + quatIdentity(_result); + } + } + + inline void quatToEuler(float* __restrict _result, const float* __restrict _quat) + { + const float x = _quat[0]; + const float y = _quat[1]; + const float z = _quat[2]; + const float w = _quat[3]; + + const float yy = y * y; + const float zz = z * z; + + const float xx = x * x; + _result[0] = fatan2(2.0f * (x * w - y * z), 1.0f - 2.0f * (xx + zz) ); + _result[1] = fatan2(2.0f * (y * w + x * z), 1.0f - 2.0f * (yy + zz) ); + _result[2] = fasin (2.0f * (x * y + z * w) ); + } + + inline void quatRotateAxis(float* __restrict _result, const float* _axis, float _angle) + { + const float ha = _angle * 0.5f; + const float ca = fcos(ha); + const float sa = fsin(ha); + _result[0] = _axis[0] * sa; + _result[1] = _axis[1] * sa; + _result[2] = _axis[2] * sa; + _result[3] = ca; + } + + inline void quatRotateX(float* _result, float _ax) + { + const float hx = _ax * 0.5f; + const float cx = fcos(hx); + const float sx = fsin(hx); + _result[0] = sx; + _result[1] = 0.0f; + _result[2] = 0.0f; + _result[3] = cx; + } + + inline void quatRotateY(float* _result, float _ay) + { + const float hy = _ay * 0.5f; + const float cy = fcos(hy); + const float sy = fsin(hy); + _result[0] = 0.0f; + _result[1] = sy; + _result[2] = 0.0f; + _result[3] = cy; + } + + inline void quatRotateZ(float* _result, float _az) + { + const float hz = _az * 0.5f; + const float cz = fcos(hz); + const float sz = fsin(hz); + _result[0] = 0.0f; + _result[1] = 0.0f; + _result[2] = sz; + _result[3] = cz; + } + + inline void vec3MulQuat(float* __restrict _result, const float* __restrict _vec, const float* __restrict _quat) + { + float tmp0[4]; + quatInvert(tmp0, _quat); + + float qv[4]; + qv[0] = _vec[0]; + qv[1] = _vec[1]; + qv[2] = _vec[2]; + qv[3] = 0.0f; + + float tmp1[4]; + quatMul(tmp1, tmp0, qv); + + quatMulXYZ(_result, tmp1, _quat); + } + + inline void mtxIdentity(float* _result) + { + memset(_result, 0, sizeof(float)*16); + _result[0] = _result[5] = _result[10] = _result[15] = 1.0f; + } + + inline void mtxTranslate(float* _result, float _tx, float _ty, float _tz) + { + mtxIdentity(_result); + _result[12] = _tx; + _result[13] = _ty; + _result[14] = _tz; + } + + inline void mtxScale(float* _result, float _sx, float _sy, float _sz) + { + memset(_result, 0, sizeof(float) * 16); + _result[0] = _sx; + _result[5] = _sy; + _result[10] = _sz; + _result[15] = 1.0f; + } + + inline void mtxScale(float* _result, float _scale) + { + mtxScale(_result, _scale, _scale, _scale); + } + + inline void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos) + { + float tangent[3]; + float bitangent[3]; + vec3TangentFrame(_normal, tangent, bitangent); + + vec3Mul(&_result[ 0], bitangent, _scale); + vec3Mul(&_result[ 4], _normal, _scale); + vec3Mul(&_result[ 8], tangent, _scale); + + _result[ 3] = 0.0f; + _result[ 7] = 0.0f; + _result[11] = 0.0f; + _result[12] = _pos[0]; + _result[13] = _pos[1]; + _result[14] = _pos[2]; + _result[15] = 1.0f; + } + + inline void mtxFromNormal(float* __restrict _result, const float* __restrict _normal, float _scale, const float* __restrict _pos, float _angle) + { + float tangent[3]; + float bitangent[3]; + vec3TangentFrame(_normal, tangent, bitangent, _angle); + + vec3Mul(&_result[ 0], bitangent, _scale); + vec3Mul(&_result[ 4], _normal, _scale); + vec3Mul(&_result[ 8], tangent, _scale); + + _result[ 3] = 0.0f; + _result[ 7] = 0.0f; + _result[11] = 0.0f; + _result[12] = _pos[0]; + _result[13] = _pos[1]; + _result[14] = _pos[2]; + _result[15] = 1.0f; + } + + inline void mtxQuat(float* __restrict _result, const float* __restrict _quat) + { + const float x = _quat[0]; + const float y = _quat[1]; + const float z = _quat[2]; + const float w = _quat[3]; + + const float x2 = x + x; + const float y2 = y + y; + const float z2 = z + z; + const float x2x = x2 * x; + const float x2y = x2 * y; + const float x2z = x2 * z; + const float x2w = x2 * w; + const float y2y = y2 * y; + const float y2z = y2 * z; + const float y2w = y2 * w; + const float z2z = z2 * z; + const float z2w = z2 * w; + + _result[ 0] = 1.0f - (y2y + z2z); + _result[ 1] = x2y - z2w; + _result[ 2] = x2z + y2w; + _result[ 3] = 0.0f; + + _result[ 4] = x2y + z2w; + _result[ 5] = 1.0f - (x2x + z2z); + _result[ 6] = y2z - x2w; + _result[ 7] = 0.0f; + + _result[ 8] = x2z - y2w; + _result[ 9] = y2z + x2w; + _result[10] = 1.0f - (x2x + y2y); + _result[11] = 0.0f; + + _result[12] = 0.0f; + _result[13] = 0.0f; + _result[14] = 0.0f; + _result[15] = 1.0f; + } + + inline void mtxQuatTranslation(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation) + { + mtxQuat(_result, _quat); + _result[12] = -(_result[0]*_translation[0] + _result[4]*_translation[1] + _result[ 8]*_translation[2]); + _result[13] = -(_result[1]*_translation[0] + _result[5]*_translation[1] + _result[ 9]*_translation[2]); + _result[14] = -(_result[2]*_translation[0] + _result[6]*_translation[1] + _result[10]*_translation[2]); + } + + inline void mtxQuatTranslationHMD(float* __restrict _result, const float* __restrict _quat, const float* __restrict _translation) + { + float quat[4]; + quat[0] = -_quat[0]; + quat[1] = -_quat[1]; + quat[2] = _quat[2]; + quat[3] = _quat[3]; + mtxQuatTranslation(_result, quat, _translation); + } + + inline void mtxLookAt_Impl(float* __restrict _result, const float* __restrict _eye, const float* __restrict _view, const float* __restrict _up) + { + float up[3] = { 0.0f, 1.0f, 0.0f }; + if (NULL != _up) + { + up[0] = _up[0]; + up[1] = _up[1]; + up[2] = _up[2]; + } + + float tmp[4]; + vec3Cross(tmp, up, _view); + + float right[4]; + vec3Norm(right, tmp); + + vec3Cross(up, _view, right); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = right[0]; + _result[ 1] = up[0]; + _result[ 2] = _view[0]; + + _result[ 4] = right[1]; + _result[ 5] = up[1]; + _result[ 6] = _view[1]; + + _result[ 8] = right[2]; + _result[ 9] = up[2]; + _result[10] = _view[2]; + + _result[12] = -vec3Dot(right, _eye); + _result[13] = -vec3Dot(up, _eye); + _result[14] = -vec3Dot(_view, _eye); + _result[15] = 1.0f; + } + + inline void mtxLookAtLh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up) + { + float tmp[4]; + vec3Sub(tmp, _at, _eye); + + float view[4]; + vec3Norm(view, tmp); + + mtxLookAt_Impl(_result, _eye, view, _up); + } + + inline void mtxLookAtRh(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up) + { + float tmp[4]; + vec3Sub(tmp, _eye, _at); + + float view[4]; + vec3Norm(view, tmp); + + mtxLookAt_Impl(_result, _eye, view, _up); + } + + inline void mtxLookAt(float* __restrict _result, const float* __restrict _eye, const float* __restrict _at, const float* __restrict _up) + { + mtxLookAtLh(_result, _eye, _at, _up); + } + + template <Handness::Enum HandnessT> + inline void mtxProjXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, float _far, bool _oglNdc) + { + const float diff = _far-_near; + const float aa = _oglNdc ? (_far+_near)/diff : _far/diff; + const float bb = _oglNdc ? (2.0f*_far*_near)/diff : _near*aa; + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = _width; + _result[ 5] = _height; + _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; + _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; + _result[10] = (Handness::Right == HandnessT) ? -aa : aa; + _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; + _result[14] = -bb; + } + + template <Handness::Enum HandnessT> + inline void mtxProj_impl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) + { + const float invDiffRl = 1.0f/(_rt - _lt); + const float invDiffUd = 1.0f/(_ut - _dt); + const float width = 2.0f*_near * invDiffRl; + const float height = 2.0f*_near * invDiffUd; + const float xx = (_rt + _lt) * invDiffRl; + const float yy = (_ut + _dt) * invDiffUd; + mtxProjXYWH<HandnessT>(_result, xx, yy, width, height, _near, _far, _oglNdc); + } + + template <Handness::Enum HandnessT> + inline void mtxProj_impl(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) + { + mtxProj_impl<HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _far, _oglNdc); + } + + template <Handness::Enum HandnessT> + inline void mtxProj_impl(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) + { + const float height = 1.0f/tanf(toRad(_fovy)*0.5f); + const float width = height * 1.0f/_aspect; + mtxProjXYWH<HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _far, _oglNdc); + } + + inline void mtxProj(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); + } + + inline void mtxProj(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); + } + + inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); + } + + inline void mtxProjLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); + } + + inline void mtxProjLh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _fov, _near, _far, _oglNdc); + } + + inline void mtxProjLh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Left>(_result, _fovy, _aspect, _near, _far, _oglNdc); + } + + inline void mtxProjRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _far, _oglNdc); + } + + inline void mtxProjRh(float* _result, const float _fov[4], float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Right>(_result, _fov, _near, _far, _oglNdc); + } + + inline void mtxProjRh(float* _result, float _fovy, float _aspect, float _near, float _far, bool _oglNdc) + { + mtxProj_impl<Handness::Right>(_result, _fovy, _aspect, _near, _far, _oglNdc); + } + + template <NearFar::Enum NearFarT, Handness::Enum HandnessT> + inline void mtxProjInfXYWH(float* _result, float _x, float _y, float _width, float _height, float _near, bool _oglNdc) + { + float aa; + float bb; + if (BX_ENABLED(NearFar::Reverse == NearFarT) ) + { + aa = _oglNdc ? -1.0f : 0.0f; + bb = _oglNdc ? -2.0f*_near : -_near; + } + else + { + aa = 1.0f; + bb = _oglNdc ? 2.0f*_near : _near; + } + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = _width; + _result[ 5] = _height; + _result[ 8] = (Handness::Right == HandnessT) ? _x : -_x; + _result[ 9] = (Handness::Right == HandnessT) ? _y : -_y; + _result[10] = (Handness::Right == HandnessT) ? -aa : aa; + _result[11] = (Handness::Right == HandnessT) ? -1.0f : 1.0f; + _result[14] = -bb; + } + + template <NearFar::Enum NearFarT, Handness::Enum HandnessT> + inline void mtxProjInf_impl(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + const float invDiffRl = 1.0f/(_rt - _lt); + const float invDiffUd = 1.0f/(_ut - _dt); + const float width = 2.0f*_near * invDiffRl; + const float height = 2.0f*_near * invDiffUd; + const float xx = (_rt + _lt) * invDiffRl; + const float yy = (_ut + _dt) * invDiffUd; + mtxProjInfXYWH<NearFarT,HandnessT>(_result, xx, yy, width, height, _near, _oglNdc); + } + + template <NearFar::Enum NearFarT, Handness::Enum HandnessT> + inline void mtxProjInf_impl(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFarT,HandnessT>(_result, _fov[0], _fov[1], _fov[2], _fov[3], _near, _oglNdc); + } + + template <NearFar::Enum NearFarT, Handness::Enum HandnessT> + inline void mtxProjInf_impl(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + const float height = 1.0f/tanf(toRad(_fovy)*0.5f); + const float width = height * 1.0f/_aspect; + mtxProjInfXYWH<NearFarT,HandnessT>(_result, 0.0f, 0.0f, width, height, _near, _oglNdc); + } + + inline void mtxProjInf(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); + } + + inline void mtxProjInf(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); + } + + inline void mtxProjInf(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); + } + + inline void mtxProjInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); + } + + inline void mtxProjInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fov, _near, _oglNdc); + } + + inline void mtxProjInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); + } + + inline void mtxProjInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); + } + + inline void mtxProjInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _fov, _near, _oglNdc); + } + + inline void mtxProjInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Default,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); + } + + inline void mtxProjRevInfLh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); + } + + inline void mtxProjRevInfLh(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _fov, _near, _oglNdc); + } + + inline void mtxProjRevInfLh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Left>(_result, _fovy, _aspect, _near, _oglNdc); + } + + inline void mtxProjRevInfRh(float* _result, float _ut, float _dt, float _lt, float _rt, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _ut, _dt, _lt, _rt, _near, _oglNdc); + } + + inline void mtxProjRevInfRh(float* _result, const float _fov[4], float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _fov, _near, _oglNdc); + } + + inline void mtxProjRevInfRh(float* _result, float _fovy, float _aspect, float _near, bool _oglNdc) + { + mtxProjInf_impl<NearFar::Reverse,Handness::Right>(_result, _fovy, _aspect, _near, _oglNdc); + } + + template <Handness::Enum HandnessT> + inline void mtxOrtho_impl(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) + { + const float aa = 2.0f/(_right - _left); + const float bb = 2.0f/(_top - _bottom); + const float cc = (_oglNdc ? 2.0f : 1.0f) / (_far - _near); + const float dd = (_left + _right)/(_left - _right); + const float ee = (_top + _bottom)/(_bottom - _top); + const float ff = _oglNdc ? (_near + _far)/(_near - _far) : _near/(_near - _far); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = aa; + _result[ 5] = bb; + _result[10] = (Handness::Right == HandnessT) ? -cc : cc; + _result[12] = dd + _offset; + _result[13] = ee; + _result[14] = ff; + _result[15] = 1.0f; + } + + inline void mtxOrtho(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) + { + mtxOrtho_impl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); + } + + inline void mtxOrthoLh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) + { + mtxOrtho_impl<Handness::Left>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); + } + + inline void mtxOrthoRh(float* _result, float _left, float _right, float _bottom, float _top, float _near, float _far, float _offset, bool _oglNdc) + { + mtxOrtho_impl<Handness::Right>(_result, _left, _right, _bottom, _top, _near, _far, _offset, _oglNdc); + } + + inline void mtxRotateX(float* _result, float _ax) + { + const float sx = fsin(_ax); + const float cx = fcos(_ax); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = 1.0f; + _result[ 5] = cx; + _result[ 6] = -sx; + _result[ 9] = sx; + _result[10] = cx; + _result[15] = 1.0f; + } + + inline void mtxRotateY(float* _result, float _ay) + { + const float sy = fsin(_ay); + const float cy = fcos(_ay); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = cy; + _result[ 2] = sy; + _result[ 5] = 1.0f; + _result[ 8] = -sy; + _result[10] = cy; + _result[15] = 1.0f; + } + + inline void mtxRotateZ(float* _result, float _az) + { + const float sz = fsin(_az); + const float cz = fcos(_az); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = cz; + _result[ 1] = -sz; + _result[ 4] = sz; + _result[ 5] = cz; + _result[10] = 1.0f; + _result[15] = 1.0f; + } + + inline void mtxRotateXY(float* _result, float _ax, float _ay) + { + const float sx = fsin(_ax); + const float cx = fcos(_ax); + const float sy = fsin(_ay); + const float cy = fcos(_ay); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = cy; + _result[ 2] = sy; + _result[ 4] = sx*sy; + _result[ 5] = cx; + _result[ 6] = -sx*cy; + _result[ 8] = -cx*sy; + _result[ 9] = sx; + _result[10] = cx*cy; + _result[15] = 1.0f; + } + + inline void mtxRotateXYZ(float* _result, float _ax, float _ay, float _az) + { + const float sx = fsin(_ax); + const float cx = fcos(_ax); + const float sy = fsin(_ay); + const float cy = fcos(_ay); + const float sz = fsin(_az); + const float cz = fcos(_az); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = cy*cz; + _result[ 1] = -cy*sz; + _result[ 2] = sy; + _result[ 4] = cz*sx*sy + cx*sz; + _result[ 5] = cx*cz - sx*sy*sz; + _result[ 6] = -cy*sx; + _result[ 8] = -cx*cz*sy + sx*sz; + _result[ 9] = cz*sx + cx*sy*sz; + _result[10] = cx*cy; + _result[15] = 1.0f; + } + + inline void mtxRotateZYX(float* _result, float _ax, float _ay, float _az) + { + const float sx = fsin(_ax); + const float cx = fcos(_ax); + const float sy = fsin(_ay); + const float cy = fcos(_ay); + const float sz = fsin(_az); + const float cz = fcos(_az); + + memset(_result, 0, sizeof(float)*16); + _result[ 0] = cy*cz; + _result[ 1] = cz*sx*sy-cx*sz; + _result[ 2] = cx*cz*sy+sx*sz; + _result[ 4] = cy*sz; + _result[ 5] = cx*cz + sx*sy*sz; + _result[ 6] = -cz*sx + cx*sy*sz; + _result[ 8] = -sy; + _result[ 9] = cy*sx; + _result[10] = cx*cy; + _result[15] = 1.0f; + }; + + inline void mtxSRT(float* _result, float _sx, float _sy, float _sz, float _ax, float _ay, float _az, float _tx, float _ty, float _tz) + { + const float sx = fsin(_ax); + const float cx = fcos(_ax); + const float sy = fsin(_ay); + const float cy = fcos(_ay); + const float sz = fsin(_az); + const float cz = fcos(_az); + + const float sxsz = sx*sz; + const float cycz = cy*cz; + + _result[ 0] = _sx * (cycz - sxsz*sy); + _result[ 1] = _sx * -cx*sz; + _result[ 2] = _sx * (cz*sy + cy*sxsz); + _result[ 3] = 0.0f; + + _result[ 4] = _sy * (cz*sx*sy + cy*sz); + _result[ 5] = _sy * cx*cz; + _result[ 6] = _sy * (sy*sz -cycz*sx); + _result[ 7] = 0.0f; + + _result[ 8] = _sz * -cx*sy; + _result[ 9] = _sz * sx; + _result[10] = _sz * cx*cy; + _result[11] = 0.0f; + + _result[12] = _tx; + _result[13] = _ty; + _result[14] = _tz; + _result[15] = 1.0f; + } + + inline void vec3MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) + { + _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12]; + _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13]; + _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14]; + } + + inline void vec3MulMtxH(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) + { + float xx = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _mat[12]; + float yy = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _mat[13]; + float zz = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _mat[14]; + float ww = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _mat[15]; + float invW = fsign(ww)/ww; + _result[0] = xx*invW; + _result[1] = yy*invW; + _result[2] = zz*invW; + } + + inline void vec4MulMtx(float* __restrict _result, const float* __restrict _vec, const float* __restrict _mat) + { + _result[0] = _vec[0] * _mat[ 0] + _vec[1] * _mat[4] + _vec[2] * _mat[ 8] + _vec[3] * _mat[12]; + _result[1] = _vec[0] * _mat[ 1] + _vec[1] * _mat[5] + _vec[2] * _mat[ 9] + _vec[3] * _mat[13]; + _result[2] = _vec[0] * _mat[ 2] + _vec[1] * _mat[6] + _vec[2] * _mat[10] + _vec[3] * _mat[14]; + _result[3] = _vec[0] * _mat[ 3] + _vec[1] * _mat[7] + _vec[2] * _mat[11] + _vec[3] * _mat[15]; + } + + inline void mtxMul(float* __restrict _result, const float* __restrict _a, const float* __restrict _b) + { + vec4MulMtx(&_result[ 0], &_a[ 0], _b); + vec4MulMtx(&_result[ 4], &_a[ 4], _b); + vec4MulMtx(&_result[ 8], &_a[ 8], _b); + vec4MulMtx(&_result[12], &_a[12], _b); + } + + inline void mtxTranspose(float* __restrict _result, const float* __restrict _a) + { + _result[ 0] = _a[ 0]; + _result[ 4] = _a[ 1]; + _result[ 8] = _a[ 2]; + _result[12] = _a[ 3]; + _result[ 1] = _a[ 4]; + _result[ 5] = _a[ 5]; + _result[ 9] = _a[ 6]; + _result[13] = _a[ 7]; + _result[ 2] = _a[ 8]; + _result[ 6] = _a[ 9]; + _result[10] = _a[10]; + _result[14] = _a[11]; + _result[ 3] = _a[12]; + _result[ 7] = _a[13]; + _result[11] = _a[14]; + _result[15] = _a[15]; + } + + /// Convert LH to RH projection matrix and vice versa. + inline void mtxProjFlipHandedness(float* __restrict _dst, const float* __restrict _src) + { + _dst[ 0] = -_src[ 0]; + _dst[ 1] = -_src[ 1]; + _dst[ 2] = -_src[ 2]; + _dst[ 3] = -_src[ 3]; + _dst[ 4] = _src[ 4]; + _dst[ 5] = _src[ 5]; + _dst[ 6] = _src[ 6]; + _dst[ 7] = _src[ 7]; + _dst[ 8] = -_src[ 8]; + _dst[ 9] = -_src[ 9]; + _dst[10] = -_src[10]; + _dst[11] = -_src[11]; + _dst[12] = _src[12]; + _dst[13] = _src[13]; + _dst[14] = _src[14]; + _dst[15] = _src[15]; + } + + /// Convert LH to RH view matrix and vice versa. + inline void mtxViewFlipHandedness(float* __restrict _dst, const float* __restrict _src) + { + _dst[ 0] = -_src[ 0]; + _dst[ 1] = _src[ 1]; + _dst[ 2] = -_src[ 2]; + _dst[ 3] = _src[ 3]; + _dst[ 4] = -_src[ 4]; + _dst[ 5] = _src[ 5]; + _dst[ 6] = -_src[ 6]; + _dst[ 7] = _src[ 7]; + _dst[ 8] = -_src[ 8]; + _dst[ 9] = _src[ 9]; + _dst[10] = -_src[10]; + _dst[11] = _src[11]; + _dst[12] = -_src[12]; + _dst[13] = _src[13]; + _dst[14] = -_src[14]; + _dst[15] = _src[15]; + } + + inline void calcNormal(float _result[3], float _va[3], float _vb[3], float _vc[3]) + { + float ba[3]; + vec3Sub(ba, _vb, _va); + + float ca[3]; + vec3Sub(ca, _vc, _va); + + float baxca[3]; + vec3Cross(baxca, ba, ca); + + vec3Norm(_result, baxca); + } + + inline void calcPlane(float _result[4], float _va[3], float _vb[3], float _vc[3]) + { + float normal[3]; + calcNormal(normal, _va, _vb, _vc); + + _result[0] = normal[0]; + _result[1] = normal[1]; + _result[2] = normal[2]; + _result[3] = -vec3Dot(normal, _va); + } + + inline void calcLinearFit2D(float _result[2], const void* _points, uint32_t _stride, uint32_t _numPoints) + { + float sumX = 0.0f; + float sumY = 0.0f; + float sumXX = 0.0f; + float sumXY = 0.0f; + + const uint8_t* ptr = (const uint8_t*)_points; + for (uint32_t ii = 0; ii < _numPoints; ++ii, ptr += _stride) + { + const float* point = (const float*)ptr; + float xx = point[0]; + float yy = point[1]; + sumX += xx; + sumY += yy; + sumXX += xx*xx; + sumXY += xx*yy; + } + + // [ sum(x^2) sum(x) ] [ A ] = [ sum(x*y) ] + // [ sum(x) numPoints ] [ B ] [ sum(y) ] + + float det = (sumXX*_numPoints - sumX*sumX); + float invDet = 1.0f/det; + + _result[0] = (-sumX * sumY + _numPoints * sumXY) * invDet; + _result[1] = (sumXX * sumY - sumX * sumXY) * invDet; + } + + inline void calcLinearFit3D(float _result[3], const void* _points, uint32_t _stride, uint32_t _numPoints) + { + float sumX = 0.0f; + float sumY = 0.0f; + float sumZ = 0.0f; + float sumXX = 0.0f; + float sumXY = 0.0f; + float sumXZ = 0.0f; + float sumYY = 0.0f; + float sumYZ = 0.0f; + + const uint8_t* ptr = (const uint8_t*)_points; + for (uint32_t ii = 0; ii < _numPoints; ++ii, ptr += _stride) + { + const float* point = (const float*)ptr; + float xx = point[0]; + float yy = point[1]; + float zz = point[2]; + + sumX += xx; + sumY += yy; + sumZ += zz; + sumXX += xx*xx; + sumXY += xx*yy; + sumXZ += xx*zz; + sumYY += yy*yy; + sumYZ += yy*zz; + } + + // [ sum(x^2) sum(x*y) sum(x) ] [ A ] [ sum(x*z) ] + // [ sum(x*y) sum(y^2) sum(y) ] [ B ] = [ sum(y*z) ] + // [ sum(x) sum(y) numPoints ] [ C ] [ sum(z) ] + + float mtx[9] = + { + sumXX, sumXY, sumX, + sumXY, sumYY, sumY, + sumX, sumY, float(_numPoints), + }; + float invMtx[9]; + mtx3Inverse(invMtx, mtx); + + _result[0] = invMtx[0]*sumXZ + invMtx[1]*sumYZ + invMtx[2]*sumZ; + _result[1] = invMtx[3]*sumXZ + invMtx[4]*sumYZ + invMtx[5]*sumZ; + _result[2] = invMtx[6]*sumXZ + invMtx[7]*sumYZ + invMtx[8]*sumZ; + } + + inline void rgbToHsv(float _hsv[3], const float _rgb[3]) + { + const float rr = _rgb[0]; + const float gg = _rgb[1]; + const float bb = _rgb[2]; + + const float s0 = fstep(bb, gg); + + const float px = flerp(bb, gg, s0); + const float py = flerp(gg, bb, s0); + const float pz = flerp(-1.0f, 0.0f, s0); + const float pw = flerp(2.0f/3.0f, -1.0f/3.0f, s0); + + const float s1 = fstep(px, rr); + + const float qx = flerp(px, rr, s1); + const float qy = py; + const float qz = flerp(pw, pz, s1); + const float qw = flerp(rr, px, s1); + + const float dd = qx - fmin(qw, qy); + const float ee = 1.0e-10f; + + _hsv[0] = fabsolute(qz + (qw - qy) / (6.0f * dd + ee) ); + _hsv[1] = dd / (qx + ee); + _hsv[2] = qx; + } + + inline void hsvToRgb(float _rgb[3], const float _hsv[3]) + { + const float hh = _hsv[0]; + const float ss = _hsv[1]; + const float vv = _hsv[2]; + + const float px = fabsolute(ffract(hh + 1.0f ) * 6.0f - 3.0f); + const float py = fabsolute(ffract(hh + 2.0f/3.0f) * 6.0f - 3.0f); + const float pz = fabsolute(ffract(hh + 1.0f/3.0f) * 6.0f - 3.0f); + + _rgb[0] = vv * flerp(1.0f, fsaturate(px - 1.0f), ss); + _rgb[1] = vv * flerp(1.0f, fsaturate(py - 1.0f), ss); + _rgb[2] = vv * flerp(1.0f, fsaturate(pz - 1.0f), ss); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/handlealloc.h b/3rdparty/bx/include/bx/handlealloc.h index 04303f4f49c..cf8efc585c5 100644 --- a/3rdparty/bx/include/bx/handlealloc.h +++ b/3rdparty/bx/include/bx/handlealloc.h @@ -18,130 +18,65 @@ namespace bx public: static const uint16_t invalid = UINT16_MAX; - HandleAlloc(uint16_t _maxHandles) - : m_numHandles(0) - , m_maxHandles(_maxHandles) - { - reset(); - } + /// + HandleAlloc(uint16_t _maxHandles); - ~HandleAlloc() - { - } + /// + ~HandleAlloc(); - const uint16_t* getHandles() const - { - return getDensePtr(); - } + /// + const uint16_t* getHandles() const; - uint16_t getHandleAt(uint16_t _at) const - { - return getDensePtr()[_at]; - } + /// + uint16_t getHandleAt(uint16_t _at) const; - uint16_t getNumHandles() const - { - return m_numHandles; - } + /// + uint16_t getNumHandles() const; - uint16_t getMaxHandles() const - { - return m_maxHandles; - } + /// + uint16_t getMaxHandles() const; - uint16_t alloc() - { - if (m_numHandles < m_maxHandles) - { - uint16_t index = m_numHandles; - ++m_numHandles; - - uint16_t* dense = getDensePtr(); - uint16_t handle = dense[index]; - uint16_t* sparse = getSparsePtr(); - sparse[handle] = index; - return handle; - } - - return invalid; - } - - bool isValid(uint16_t _handle) const - { - uint16_t* dense = getDensePtr(); - uint16_t* sparse = getSparsePtr(); - uint16_t index = sparse[_handle]; + /// + uint16_t alloc(); - return index < m_numHandles - && dense[index] == _handle - ; - } + /// + bool isValid(uint16_t _handle) const; - void free(uint16_t _handle) - { - uint16_t* dense = getDensePtr(); - uint16_t* sparse = getSparsePtr(); - uint16_t index = sparse[_handle]; - --m_numHandles; - uint16_t temp = dense[m_numHandles]; - dense[m_numHandles] = _handle; - sparse[temp] = index; - dense[index] = temp; - } - - void reset() - { - m_numHandles = 0; - uint16_t* dense = getDensePtr(); - for (uint16_t ii = 0, num = m_maxHandles; ii < num; ++ii) - { - dense[ii] = ii; - } - } + /// + void free(uint16_t _handle); + + /// + void reset(); private: HandleAlloc(); - uint16_t* getDensePtr() const - { - uint8_t* ptr = (uint8_t*)reinterpret_cast<const uint8_t*>(this); - return (uint16_t*)&ptr[sizeof(HandleAlloc)]; - } + /// + uint16_t* getDensePtr() const; - uint16_t* getSparsePtr() const - { - return &getDensePtr()[m_maxHandles]; - } + /// + uint16_t* getSparsePtr() const; uint16_t m_numHandles; uint16_t m_maxHandles; }; - inline HandleAlloc* createHandleAlloc(AllocatorI* _allocator, uint16_t _maxHandles) - { - uint8_t* ptr = (uint8_t*)BX_ALLOC(_allocator, sizeof(HandleAlloc) + 2*_maxHandles*sizeof(uint16_t) ); - return ::new (ptr) HandleAlloc(_maxHandles); - } + /// + HandleAlloc* createHandleAlloc(AllocatorI* _allocator, uint16_t _maxHandles); - inline void destroyHandleAlloc(AllocatorI* _allocator, HandleAlloc* _handleAlloc) - { - _handleAlloc->~HandleAlloc(); - BX_FREE(_allocator, _handleAlloc); - } + /// + void destroyHandleAlloc(AllocatorI* _allocator, HandleAlloc* _handleAlloc); /// template <uint16_t MaxHandlesT> class HandleAllocT : public HandleAlloc { public: - HandleAllocT() - : HandleAlloc(MaxHandlesT) - { - } + /// + HandleAllocT(); - ~HandleAllocT() - { - } + /// + ~HandleAllocT(); private: uint16_t m_padding[2*MaxHandlesT]; @@ -154,170 +89,51 @@ namespace bx public: static const uint16_t invalid = UINT16_MAX; - HandleListT() - { - reset(); - } + /// + HandleListT(); - void pushBack(uint16_t _handle) - { - insertAfter(m_back, _handle); - } + /// + void pushBack(uint16_t _handle); - uint16_t popBack() - { - uint16_t last = invalid != m_back - ? m_back - : m_front - ; + /// + uint16_t popBack(); - if (invalid != last) - { - remove(last); - } + /// + void pushFront(uint16_t _handle); - return last; - } + /// + uint16_t popFront(); - void pushFront(uint16_t _handle) - { - insertBefore(m_front, _handle); - } - - uint16_t popFront() - { - uint16_t front = m_front; + /// + uint16_t getFront() const; - if (invalid != front) - { - remove(front); - } + /// + uint16_t getBack() const; - return front; - } + /// + uint16_t getNext(uint16_t _handle) const; - uint16_t getFront() const - { - return m_front; - } + /// + uint16_t getPrev(uint16_t _handle) const; - uint16_t getBack() const - { - return m_back; - } + /// + void remove(uint16_t _handle); - uint16_t getNext(uint16_t _handle) const - { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); - const Link& curr = m_links[_handle]; - return curr.m_next; - } - - uint16_t getPrev(uint16_t _handle) const - { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); - const Link& curr = m_links[_handle]; - return curr.m_prev; - } - - void remove(uint16_t _handle) - { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); - Link& curr = m_links[_handle]; - - if (invalid != curr.m_prev) - { - Link& prev = m_links[curr.m_prev]; - prev.m_next = curr.m_next; - } - else - { - m_front = curr.m_next; - } - - if (invalid != curr.m_next) - { - Link& next = m_links[curr.m_next]; - next.m_prev = curr.m_prev; - } - else - { - m_back = curr.m_prev; - } - - curr.m_prev = invalid; - curr.m_next = invalid; - } - - void reset() - { - memset(m_links, 0xff, sizeof(m_links) ); - m_front = invalid; - m_back = invalid; - } + /// + void reset(); private: - void insertBefore(uint16_t _before, uint16_t _handle) - { - Link& curr = m_links[_handle]; - curr.m_next = _before; - - if (invalid != _before) - { - Link& link = m_links[_before]; - if (invalid != link.m_prev) - { - Link& prev = m_links[link.m_prev]; - prev.m_next = _handle; - } - - curr.m_prev = link.m_prev; - link.m_prev = _handle; - } - - updateFrontBack(_handle); - } - - void insertAfter(uint16_t _after, uint16_t _handle) - { - Link& curr = m_links[_handle]; - curr.m_prev = _after; - - if (invalid != _after) - { - Link& link = m_links[_after]; - if (invalid != link.m_next) - { - Link& next = m_links[link.m_next]; - next.m_prev = _handle; - } - - curr.m_next = link.m_next; - link.m_next = _handle; - } - - updateFrontBack(_handle); - } - - bool isValid(uint16_t _handle) const - { - return _handle < MaxHandlesT; - } + /// + void insertBefore(uint16_t _before, uint16_t _handle); - void updateFrontBack(uint16_t _handle) - { - Link& curr = m_links[_handle]; + /// + void insertAfter(uint16_t _after, uint16_t _handle); - if (invalid == curr.m_prev) - { - m_front = _handle; - } + /// + bool isValid(uint16_t _handle) const; - if (invalid == curr.m_next) - { - m_back = _handle; - } - } + /// + void updateFrontBack(uint16_t _handle); uint16_t m_front; uint16_t m_back; @@ -338,89 +154,50 @@ namespace bx public: static const uint16_t invalid = UINT16_MAX; - HandleAllocLruT() - { - reset(); - } + /// + HandleAllocLruT(); - ~HandleAllocLruT() - { - } + /// + ~HandleAllocLruT(); - const uint16_t* getHandles() const - { - return m_alloc.getHandles(); - } + /// + const uint16_t* getHandles() const; - uint16_t getHandleAt(uint16_t _at) const - { - return m_alloc.getHandleAt(_at); - } + /// + uint16_t getHandleAt(uint16_t _at) const; - uint16_t getNumHandles() const - { - return m_alloc.getNumHandles(); - } + /// + uint16_t getNumHandles() const; - uint16_t getMaxHandles() const - { - return m_alloc.getMaxHandles(); - } + /// + uint16_t getMaxHandles() const; - uint16_t alloc() - { - uint16_t handle = m_alloc.alloc(); - if (invalid != handle) - { - m_list.pushFront(handle); - } - return handle; - } - - bool isValid(uint16_t _handle) const - { - return m_alloc.isValid(_handle); - } + /// + uint16_t alloc(); - void free(uint16_t _handle) - { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); - m_list.remove(_handle); - m_alloc.free(_handle); - } + /// + bool isValid(uint16_t _handle) const; - void touch(uint16_t _handle) - { - BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); - m_list.remove(_handle); - m_list.pushFront(_handle); - } + /// + void free(uint16_t _handle); - uint16_t getFront() const - { - return m_list.getFront(); - } + /// + void touch(uint16_t _handle); - uint16_t getBack() const - { - return m_list.getBack(); - } + /// + uint16_t getFront() const; - uint16_t getNext(uint16_t _handle) const - { - return m_list.getNext(_handle); - } + /// + uint16_t getBack() const; - uint16_t getPrev(uint16_t _handle) const - { - return m_list.getPrev(_handle); - } + /// + uint16_t getNext(uint16_t _handle) const; - void reset() - { - m_list.reset(); - m_alloc.reset(); - } + /// + uint16_t getPrev(uint16_t _handle) const; + + /// + void reset(); private: HandleListT<MaxHandlesT> m_list; @@ -434,103 +211,34 @@ namespace bx public: static const uint16_t invalid = UINT16_MAX; - HandleHashMapT() - : m_maxCapacity(MaxCapacityT) - { - reset(); - } + /// + HandleHashMapT(); - ~HandleHashMapT() - { - } + /// + ~HandleHashMapT(); - bool insert(KeyT _key, uint16_t _handle) - { - if (invalid == _handle) - { - return false; - } - - const KeyT hash = mix(_key); - const uint32_t firstIdx = hash % MaxCapacityT; - uint32_t idx = firstIdx; - do - { - if (m_handle[idx] == invalid) - { - m_key[idx] = _key; - m_handle[idx] = _handle; - ++m_numElements; - return true; - } - - if (m_key[idx] == _key) - { - return false; - } - - idx = (idx + 1) % MaxCapacityT; - - } while (idx != firstIdx); - - return false; - } - - bool removeByKey(KeyT _key) - { - uint32_t idx = findIndex(_key); - if (UINT32_MAX != idx) - { - removeIndex(idx); - return true; - } + /// + bool insert(KeyT _key, uint16_t _handle); - return false; - } + /// + bool removeByKey(KeyT _key); - bool removeByHandle(uint16_t _handle) - { - if (invalid != _handle) - { - for (uint32_t idx = 0; idx < MaxCapacityT; ++idx) - { - if (m_handle[idx] == _handle) - { - removeIndex(idx); - } - } - } - - return false; - } - - uint16_t find(KeyT _key) const - { - uint32_t idx = findIndex(_key); - if (UINT32_MAX != idx) - { - return m_handle[idx]; - } + /// + bool removeByHandle(uint16_t _handle); - return invalid; - } + /// + uint16_t find(KeyT _key) const; - void reset() - { - memset(m_handle, 0xff, sizeof(m_handle) ); - m_numElements = 0; - } + /// + void reset(); - uint32_t getNumElements() const - { - return m_numElements; - } + /// + uint32_t getNumElements() const; - uint32_t getMaxCapacity() const - { - return m_maxCapacity; - } + /// + uint32_t getMaxCapacity() const; + /// struct Iterator { uint16_t handle; @@ -541,104 +249,24 @@ namespace bx uint32_t num; }; - Iterator first() const - { - Iterator it; - it.handle = invalid; - it.pos = 0; - it.num = m_numElements; - - if (0 == it.num) - { - return it; - } - - ++it.num; - next(it); - return it; - } - - bool next(Iterator& _it) const - { - if (0 == _it.num) - { - return false; - } - - for ( - ;_it.pos < MaxCapacityT && invalid == m_handle[_it.pos] - ; ++_it.pos - ); - _it.handle = m_handle[_it.pos]; - ++_it.pos; - --_it.num; - return true; - } + /// + Iterator first() const; - private: - uint32_t findIndex(KeyT _key) const - { - const KeyT hash = mix(_key); - - const uint32_t firstIdx = hash % MaxCapacityT; - uint32_t idx = firstIdx; - do - { - if (m_handle[idx] == invalid) - { - return UINT32_MAX; - } - - if (m_key[idx] == _key) - { - return idx; - } + /// + bool next(Iterator& _it) const; - idx = (idx + 1) % MaxCapacityT; + private: + /// + uint32_t findIndex(KeyT _key) const; - } while (idx != firstIdx); + /// + void removeIndex(uint32_t _idx); - return UINT32_MAX; - } + /// + uint32_t mix(uint32_t _x) const; - void removeIndex(uint32_t _idx) - { - m_handle[_idx] = invalid; - --m_numElements; - - for (uint32_t idx = (_idx + 1) % MaxCapacityT - ; m_handle[idx] != invalid - ; idx = (idx + 1) % MaxCapacityT) - { - if (m_handle[idx] != invalid) - { - const KeyT key = m_key[idx]; - if (idx != findIndex(key) ) - { - const uint16_t handle = m_handle[idx]; - m_handle[idx] = invalid; - --m_numElements; - insert(key, handle); - } - } - } - } - - uint32_t mix(uint32_t _x) const - { - const uint32_t tmp0 = uint32_mul(_x, UINT32_C(2246822519) ); - const uint32_t tmp1 = uint32_rol(tmp0, 13); - const uint32_t result = uint32_mul(tmp1, UINT32_C(2654435761) ); - return result; - } - - uint64_t mix(uint64_t _x) const - { - const uint64_t tmp0 = uint64_mul(_x, UINT64_C(14029467366897019727) ); - const uint64_t tmp1 = uint64_rol(tmp0, 31); - const uint64_t result = uint64_mul(tmp1, UINT64_C(11400714785074694791) ); - return result; - } + /// + uint64_t mix(uint64_t _x) const; uint32_t m_maxCapacity; uint32_t m_numElements; @@ -654,86 +282,41 @@ namespace bx public: static const uint16_t invalid = UINT16_MAX; - HandleHashMapAllocT() - { - reset(); - } + /// + HandleHashMapAllocT(); - ~HandleHashMapAllocT() - { - } + /// + ~HandleHashMapAllocT(); - uint16_t alloc(KeyT _key) - { - uint16_t handle = m_alloc.alloc(); - if (invalid == handle) - { - return invalid; - } - - bool ok = m_table.insert(_key, handle); - if (!ok) - { - m_alloc.free(handle); - return invalid; - } - - return handle; - } - - void free(KeyT _key) - { - uint16_t handle = m_table.find(_key); - if (invalid == handle) - { - return; - } + /// + uint16_t alloc(KeyT _key); - m_table.removeByKey(_key); - m_alloc.free(handle); - } + /// + void free(KeyT _key); - void free(uint16_t _handle) - { - m_table.removeByHandle(_handle); - m_alloc.free(_handle); - } + /// + void free(uint16_t _handle); - uint16_t find(KeyT _key) const - { - return m_table.find(_key); - } + /// + uint16_t find(KeyT _key) const; - const uint16_t* getHandles() const - { - return m_alloc.getHandles(); - } + /// + const uint16_t* getHandles() const; - uint16_t getHandleAt(uint16_t _at) const - { - return m_alloc.getHandleAt(_at); - } + /// + uint16_t getHandleAt(uint16_t _at) const; - uint16_t getNumHandles() const - { - return m_alloc.getNumHandles(); - } + /// + uint16_t getNumHandles() const; - uint16_t getMaxHandles() const - { - return m_alloc.getMaxHandles(); - } + /// + uint16_t getMaxHandles() const; - bool isValid(uint16_t _handle) const - { - return m_alloc.isValid(_handle); - } + /// + bool isValid(uint16_t _handle) const; - void reset() - { - m_table.reset(); - m_alloc.reset(); - } + /// + void reset(); private: HandleHashMapT<MaxHandlesT+MaxHandlesT/2, KeyT> m_table; @@ -742,4 +325,6 @@ namespace bx } // namespace bx +#include "handlealloc.inl" + #endif // BX_HANDLE_ALLOC_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/handlealloc.inl b/3rdparty/bx/include/bx/handlealloc.inl new file mode 100644 index 00000000000..04369b57d78 --- /dev/null +++ b/3rdparty/bx/include/bx/handlealloc.inl @@ -0,0 +1,712 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_HANDLE_ALLOC_H_HEADER_GUARD +# error "Must be included from bx/handlealloc.h!" +#endif // BX_HANDLE_ALLOC_H_HEADER_GUARD + +#include "bx.h" +#include "allocator.h" +#include "uint32_t.h" + +namespace bx +{ + inline HandleAlloc::HandleAlloc(uint16_t _maxHandles) + : m_numHandles(0) + , m_maxHandles(_maxHandles) + { + reset(); + } + + inline HandleAlloc::~HandleAlloc() + { + } + + inline const uint16_t* HandleAlloc::getHandles() const + { + return getDensePtr(); + } + + inline uint16_t HandleAlloc::getHandleAt(uint16_t _at) const + { + return getDensePtr()[_at]; + } + + inline uint16_t HandleAlloc::getNumHandles() const + { + return m_numHandles; + } + + inline uint16_t HandleAlloc::getMaxHandles() const + { + return m_maxHandles; + } + + inline uint16_t HandleAlloc::alloc() + { + if (m_numHandles < m_maxHandles) + { + uint16_t index = m_numHandles; + ++m_numHandles; + + uint16_t* dense = getDensePtr(); + uint16_t handle = dense[index]; + uint16_t* sparse = getSparsePtr(); + sparse[handle] = index; + return handle; + } + + return invalid; + } + + inline bool HandleAlloc::isValid(uint16_t _handle) const + { + uint16_t* dense = getDensePtr(); + uint16_t* sparse = getSparsePtr(); + uint16_t index = sparse[_handle]; + + return index < m_numHandles + && dense[index] == _handle + ; + } + + inline void HandleAlloc::free(uint16_t _handle) + { + uint16_t* dense = getDensePtr(); + uint16_t* sparse = getSparsePtr(); + uint16_t index = sparse[_handle]; + --m_numHandles; + uint16_t temp = dense[m_numHandles]; + dense[m_numHandles] = _handle; + sparse[temp] = index; + dense[index] = temp; + } + + inline void HandleAlloc::reset() + { + m_numHandles = 0; + uint16_t* dense = getDensePtr(); + for (uint16_t ii = 0, num = m_maxHandles; ii < num; ++ii) + { + dense[ii] = ii; + } + } + + inline uint16_t* HandleAlloc::getDensePtr() const + { + uint8_t* ptr = (uint8_t*)reinterpret_cast<const uint8_t*>(this); + return (uint16_t*)&ptr[sizeof(HandleAlloc)]; + } + + inline uint16_t* HandleAlloc::getSparsePtr() const + { + return &getDensePtr()[m_maxHandles]; + } + + inline HandleAlloc* createHandleAlloc(AllocatorI* _allocator, uint16_t _maxHandles) + { + uint8_t* ptr = (uint8_t*)BX_ALLOC(_allocator, sizeof(HandleAlloc) + 2*_maxHandles*sizeof(uint16_t) ); + return ::new (ptr) HandleAlloc(_maxHandles); + } + + inline void destroyHandleAlloc(AllocatorI* _allocator, HandleAlloc* _handleAlloc) + { + _handleAlloc->~HandleAlloc(); + BX_FREE(_allocator, _handleAlloc); + } + + template <uint16_t MaxHandlesT> + inline HandleAllocT<MaxHandlesT>::HandleAllocT() + : HandleAlloc(MaxHandlesT) + { + } + + template <uint16_t MaxHandlesT> + inline HandleAllocT<MaxHandlesT>::~HandleAllocT() + { + } + + template <uint16_t MaxHandlesT> + inline HandleListT<MaxHandlesT>::HandleListT() + { + reset(); + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::pushBack(uint16_t _handle) + { + insertAfter(m_back, _handle); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::popBack() + { + uint16_t last = invalid != m_back + ? m_back + : m_front + ; + + if (invalid != last) + { + remove(last); + } + + return last; + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::pushFront(uint16_t _handle) + { + insertBefore(m_front, _handle); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::popFront() + { + uint16_t front = m_front; + + if (invalid != front) + { + remove(front); + } + + return front; + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::getFront() const + { + return m_front; + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::getBack() const + { + return m_back; + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::getNext(uint16_t _handle) const + { + BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + const Link& curr = m_links[_handle]; + return curr.m_next; + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleListT<MaxHandlesT>::getPrev(uint16_t _handle) const + { + BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + const Link& curr = m_links[_handle]; + return curr.m_prev; + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::remove(uint16_t _handle) + { + BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + Link& curr = m_links[_handle]; + + if (invalid != curr.m_prev) + { + Link& prev = m_links[curr.m_prev]; + prev.m_next = curr.m_next; + } + else + { + m_front = curr.m_next; + } + + if (invalid != curr.m_next) + { + Link& next = m_links[curr.m_next]; + next.m_prev = curr.m_prev; + } + else + { + m_back = curr.m_prev; + } + + curr.m_prev = invalid; + curr.m_next = invalid; + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::reset() + { + memset(m_links, 0xff, sizeof(m_links) ); + m_front = invalid; + m_back = invalid; + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::insertBefore(uint16_t _before, uint16_t _handle) + { + Link& curr = m_links[_handle]; + curr.m_next = _before; + + if (invalid != _before) + { + Link& link = m_links[_before]; + if (invalid != link.m_prev) + { + Link& prev = m_links[link.m_prev]; + prev.m_next = _handle; + } + + curr.m_prev = link.m_prev; + link.m_prev = _handle; + } + + updateFrontBack(_handle); + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::insertAfter(uint16_t _after, uint16_t _handle) + { + Link& curr = m_links[_handle]; + curr.m_prev = _after; + + if (invalid != _after) + { + Link& link = m_links[_after]; + if (invalid != link.m_next) + { + Link& next = m_links[link.m_next]; + next.m_prev = _handle; + } + + curr.m_next = link.m_next; + link.m_next = _handle; + } + + updateFrontBack(_handle); + } + + template <uint16_t MaxHandlesT> + inline bool HandleListT<MaxHandlesT>::isValid(uint16_t _handle) const + { + return _handle < MaxHandlesT; + } + + template <uint16_t MaxHandlesT> + inline void HandleListT<MaxHandlesT>::updateFrontBack(uint16_t _handle) + { + Link& curr = m_links[_handle]; + + if (invalid == curr.m_prev) + { + m_front = _handle; + } + + if (invalid == curr.m_next) + { + m_back = _handle; + } + } + + template <uint16_t MaxHandlesT> + inline HandleAllocLruT<MaxHandlesT>::HandleAllocLruT() + { + reset(); + } + + template <uint16_t MaxHandlesT> + inline HandleAllocLruT<MaxHandlesT>::~HandleAllocLruT() + { + } + + template <uint16_t MaxHandlesT> + inline const uint16_t* HandleAllocLruT<MaxHandlesT>::getHandles() const + { + return m_alloc.getHandles(); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getHandleAt(uint16_t _at) const + { + return m_alloc.getHandleAt(_at); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getNumHandles() const + { + return m_alloc.getNumHandles(); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getMaxHandles() const + { + return m_alloc.getMaxHandles(); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::alloc() + { + uint16_t handle = m_alloc.alloc(); + if (invalid != handle) + { + m_list.pushFront(handle); + } + return handle; + } + + template <uint16_t MaxHandlesT> + inline bool HandleAllocLruT<MaxHandlesT>::isValid(uint16_t _handle) const + { + return m_alloc.isValid(_handle); + } + + template <uint16_t MaxHandlesT> + inline void HandleAllocLruT<MaxHandlesT>::free(uint16_t _handle) + { + BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + m_list.remove(_handle); + m_alloc.free(_handle); + } + + template <uint16_t MaxHandlesT> + inline void HandleAllocLruT<MaxHandlesT>::touch(uint16_t _handle) + { + BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle); + m_list.remove(_handle); + m_list.pushFront(_handle); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getFront() const + { + return m_list.getFront(); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getBack() const + { + return m_list.getBack(); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getNext(uint16_t _handle) const + { + return m_list.getNext(_handle); + } + + template <uint16_t MaxHandlesT> + inline uint16_t HandleAllocLruT<MaxHandlesT>::getPrev(uint16_t _handle) const + { + return m_list.getPrev(_handle); + } + + template <uint16_t MaxHandlesT> + inline void HandleAllocLruT<MaxHandlesT>::reset() + { + m_list.reset(); + m_alloc.reset(); + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline HandleHashMapT<MaxCapacityT, KeyT>::HandleHashMapT() + : m_maxCapacity(MaxCapacityT) + { + reset(); + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline HandleHashMapT<MaxCapacityT, KeyT>::~HandleHashMapT() + { + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline bool HandleHashMapT<MaxCapacityT, KeyT>::insert(KeyT _key, uint16_t _handle) + { + if (invalid == _handle) + { + return false; + } + + const KeyT hash = mix(_key); + const uint32_t firstIdx = hash % MaxCapacityT; + uint32_t idx = firstIdx; + do + { + if (m_handle[idx] == invalid) + { + m_key[idx] = _key; + m_handle[idx] = _handle; + ++m_numElements; + return true; + } + + if (m_key[idx] == _key) + { + return false; + } + + idx = (idx + 1) % MaxCapacityT; + + } while (idx != firstIdx); + + return false; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline bool HandleHashMapT<MaxCapacityT, KeyT>::removeByKey(KeyT _key) + { + uint32_t idx = findIndex(_key); + if (UINT32_MAX != idx) + { + removeIndex(idx); + return true; + } + + return false; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline bool HandleHashMapT<MaxCapacityT, KeyT>::removeByHandle(uint16_t _handle) + { + if (invalid != _handle) + { + for (uint32_t idx = 0; idx < MaxCapacityT; ++idx) + { + if (m_handle[idx] == _handle) + { + removeIndex(idx); + } + } + } + + return false; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint16_t HandleHashMapT<MaxCapacityT, KeyT>::find(KeyT _key) const + { + uint32_t idx = findIndex(_key); + if (UINT32_MAX != idx) + { + return m_handle[idx]; + } + + return invalid; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline void HandleHashMapT<MaxCapacityT, KeyT>::reset() + { + memset(m_handle, 0xff, sizeof(m_handle) ); + m_numElements = 0; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::getNumElements() const + { + return m_numElements; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::getMaxCapacity() const + { + return m_maxCapacity; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline typename HandleHashMapT<MaxCapacityT, KeyT>::Iterator HandleHashMapT<MaxCapacityT, KeyT>::first() const + { + Iterator it; + it.handle = invalid; + it.pos = 0; + it.num = m_numElements; + + if (0 == it.num) + { + return it; + } + + ++it.num; + next(it); + return it; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline bool HandleHashMapT<MaxCapacityT, KeyT>::next(Iterator& _it) const + { + if (0 == _it.num) + { + return false; + } + + for ( + ;_it.pos < MaxCapacityT && invalid == m_handle[_it.pos] + ; ++_it.pos + ); + _it.handle = m_handle[_it.pos]; + ++_it.pos; + --_it.num; + return true; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::findIndex(KeyT _key) const + { + const KeyT hash = mix(_key); + + const uint32_t firstIdx = hash % MaxCapacityT; + uint32_t idx = firstIdx; + do + { + if (m_handle[idx] == invalid) + { + return UINT32_MAX; + } + + if (m_key[idx] == _key) + { + return idx; + } + + idx = (idx + 1) % MaxCapacityT; + + } while (idx != firstIdx); + + return UINT32_MAX; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline void HandleHashMapT<MaxCapacityT, KeyT>::removeIndex(uint32_t _idx) + { + m_handle[_idx] = invalid; + --m_numElements; + + for (uint32_t idx = (_idx + 1) % MaxCapacityT + ; m_handle[idx] != invalid + ; idx = (idx + 1) % MaxCapacityT) + { + if (m_handle[idx] != invalid) + { + const KeyT key = m_key[idx]; + if (idx != findIndex(key) ) + { + const uint16_t handle = m_handle[idx]; + m_handle[idx] = invalid; + --m_numElements; + insert(key, handle); + } + } + } + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint32_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint32_t _x) const + { + const uint32_t tmp0 = uint32_mul(_x, UINT32_C(2246822519) ); + const uint32_t tmp1 = uint32_rol(tmp0, 13); + const uint32_t result = uint32_mul(tmp1, UINT32_C(2654435761) ); + return result; + } + + template <uint32_t MaxCapacityT, typename KeyT> + inline uint64_t HandleHashMapT<MaxCapacityT, KeyT>::mix(uint64_t _x) const + { + const uint64_t tmp0 = uint64_mul(_x, UINT64_C(14029467366897019727) ); + const uint64_t tmp1 = uint64_rol(tmp0, 31); + const uint64_t result = uint64_mul(tmp1, UINT64_C(11400714785074694791) ); + return result; + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline HandleHashMapAllocT<MaxHandlesT, KeyT>::HandleHashMapAllocT() + { + reset(); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline HandleHashMapAllocT<MaxHandlesT, KeyT>::~HandleHashMapAllocT() + { + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline uint16_t HandleHashMapAllocT<MaxHandlesT, KeyT>::alloc(KeyT _key) + { + uint16_t handle = m_alloc.alloc(); + if (invalid == handle) + { + return invalid; + } + + bool ok = m_table.insert(_key, handle); + if (!ok) + { + m_alloc.free(handle); + return invalid; + } + + return handle; + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline void HandleHashMapAllocT<MaxHandlesT, KeyT>::free(KeyT _key) + { + uint16_t handle = m_table.find(_key); + if (invalid == handle) + { + return; + } + + m_table.removeByKey(_key); + m_alloc.free(handle); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline void HandleHashMapAllocT<MaxHandlesT, KeyT>::free(uint16_t _handle) + { + m_table.removeByHandle(_handle); + m_alloc.free(_handle); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline uint16_t HandleHashMapAllocT<MaxHandlesT, KeyT>::find(KeyT _key) const + { + return m_table.find(_key); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline const uint16_t* HandleHashMapAllocT<MaxHandlesT, KeyT>::getHandles() const + { + return m_alloc.getHandles(); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline uint16_t HandleHashMapAllocT<MaxHandlesT, KeyT>::getHandleAt(uint16_t _at) const + { + return m_alloc.getHandleAt(_at); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline uint16_t HandleHashMapAllocT<MaxHandlesT, KeyT>::getNumHandles() const + { + return m_alloc.getNumHandles(); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline uint16_t HandleHashMapAllocT<MaxHandlesT, KeyT>::getMaxHandles() const + { + return m_alloc.getMaxHandles(); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline bool HandleHashMapAllocT<MaxHandlesT, KeyT>::isValid(uint16_t _handle) const + { + return m_alloc.isValid(_handle); + } + + template <uint16_t MaxHandlesT, typename KeyT> + inline void HandleHashMapAllocT<MaxHandlesT, KeyT>::reset() + { + m_table.reset(); + m_alloc.reset(); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/hash.h b/3rdparty/bx/include/bx/hash.h index d037c30a3c1..ec0b8164bd0 100644 --- a/3rdparty/bx/include/bx/hash.h +++ b/3rdparty/bx/include/bx/hash.h @@ -6,139 +6,41 @@ #ifndef BX_HASH_H_HEADER_GUARD #define BX_HASH_H_HEADER_GUARD -#include "bx.h" +#include "allocator.h" // isAligned namespace bx { -// MurmurHash2 was written by Austin Appleby, and is placed in the public -// domain. The author hereby disclaims copyright to this source code. - -#define MURMUR_M 0x5bd1e995 -#define MURMUR_R 24 -#define mmix(_h, _k) { _k *= MURMUR_M; _k ^= _k >> MURMUR_R; _k *= MURMUR_M; _h *= MURMUR_M; _h ^= _k; } - + /// MurmurHash2 was written by Austin Appleby, and is placed in the public + /// domain. The author hereby disclaims copyright to this source code. + /// class HashMurmur2A { public: - void begin(uint32_t _seed = 0) - { - m_hash = _seed; - m_tail = 0; - m_count = 0; - m_size = 0; - } - - void add(const void* _data, int _len) - { - if (BX_UNLIKELY(!isPtrAligned(_data, 4) ) ) - { - addUnaligned(_data, _len); - return; - } - - addAligned(_data, _len); - } - - void addAligned(const void* _data, int _len) - { - const uint8_t* data = (const uint8_t*)_data; - m_size += _len; - - mixTail(data, _len); - - while(_len >= 4) - { - uint32_t kk = *(uint32_t*)data; - - mmix(m_hash, kk); - - data += 4; - _len -= 4; - } - - mixTail(data, _len); - } + /// + void begin(uint32_t _seed = 0); - void addUnaligned(const void* _data, int _len) - { - const uint8_t* data = (const uint8_t*)_data; - m_size += _len; + /// + void add(const void* _data, int _len); - mixTail(data, _len); + /// + void addAligned(const void* _data, int _len); - while(_len >= 4) - { - uint32_t kk; - readUnaligned(data, kk); - - mmix(m_hash, kk); - - data += 4; - _len -= 4; - } - - mixTail(data, _len); - } + /// + void addUnaligned(const void* _data, int _len); + /// template<typename Ty> - void add(Ty _value) - { - add(&_value, sizeof(Ty) ); - } - - uint32_t end() - { - mmix(m_hash, m_tail); - mmix(m_hash, m_size); - - m_hash ^= m_hash >> 13; - m_hash *= MURMUR_M; - m_hash ^= m_hash >> 15; + void add(Ty _value); - return m_hash; - } + /// + uint32_t end(); private: - static void readUnaligned(const void* _data, uint32_t& _out) - { - const uint8_t* data = (const uint8_t*)_data; - if (BX_ENABLED(BX_CPU_ENDIAN_BIG) ) - { - _out = 0 - | data[0]<<24 - | data[1]<<16 - | data[2]<<8 - | data[3] - ; - } - else - { - _out = 0 - | data[0] - | data[1]<<8 - | data[2]<<16 - | data[3]<<24 - ; - } - } - - void mixTail(const uint8_t*& _data, int& _len) - { - while( _len && ((_len<4) || m_count) ) - { - m_tail |= (*_data++) << (m_count * 8); - - m_count++; - _len--; - - if(m_count == 4) - { - mmix(m_hash, m_tail); - m_tail = 0; - m_count = 0; - } - } - } + /// + static void readUnaligned(const void* _data, uint32_t& _out); + + /// + void mixTail(const uint8_t*& _data, int& _len); uint32_t m_hash; uint32_t m_tail; @@ -146,25 +48,15 @@ namespace bx uint32_t m_size; }; -#undef MURMUR_M -#undef MURMUR_R -#undef mmix - - inline uint32_t hashMurmur2A(const void* _data, uint32_t _size) - { - HashMurmur2A murmur; - murmur.begin(); - murmur.add(_data, (int)_size); - return murmur.end(); - } + /// + uint32_t hashMurmur2A(const void* _data, uint32_t _size); + /// template <typename Ty> - inline uint32_t hashMurmur2A(const Ty& _data) - { - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - return hashMurmur2A(&_data, sizeof(Ty) ); - } + uint32_t hashMurmur2A(const Ty& _data); } // namespace bx +#include "hash.inl" + #endif // BX_HASH_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/hash.inl b/3rdparty/bx/include/bx/hash.inl new file mode 100644 index 00000000000..cfa3eca252c --- /dev/null +++ b/3rdparty/bx/include/bx/hash.inl @@ -0,0 +1,154 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_HASH_H_HEADER_GUARD +# error "Must be included from bx/hash.h!" +#endif // BX_HASH_H_HEADER_GUARD + +namespace bx +{ +#define MURMUR_M 0x5bd1e995 +#define MURMUR_R 24 +#define mmix(_h, _k) { _k *= MURMUR_M; _k ^= _k >> MURMUR_R; _k *= MURMUR_M; _h *= MURMUR_M; _h ^= _k; } + + inline void HashMurmur2A::begin(uint32_t _seed) + { + m_hash = _seed; + m_tail = 0; + m_count = 0; + m_size = 0; + } + + inline void HashMurmur2A::add(const void* _data, int _len) + { + if (BX_UNLIKELY(!isAligned(_data, 4) ) ) + { + addUnaligned(_data, _len); + return; + } + + addAligned(_data, _len); + } + + inline void HashMurmur2A::addAligned(const void* _data, int _len) + { + const uint8_t* data = (const uint8_t*)_data; + m_size += _len; + + mixTail(data, _len); + + while(_len >= 4) + { + uint32_t kk = *(uint32_t*)data; + + mmix(m_hash, kk); + + data += 4; + _len -= 4; + } + + mixTail(data, _len); + } + + inline void HashMurmur2A::addUnaligned(const void* _data, int _len) + { + const uint8_t* data = (const uint8_t*)_data; + m_size += _len; + + mixTail(data, _len); + + while(_len >= 4) + { + uint32_t kk; + readUnaligned(data, kk); + + mmix(m_hash, kk); + + data += 4; + _len -= 4; + } + + mixTail(data, _len); + } + + template<typename Ty> + inline void HashMurmur2A::add(Ty _value) + { + add(&_value, sizeof(Ty) ); + } + + inline uint32_t HashMurmur2A::end() + { + mmix(m_hash, m_tail); + mmix(m_hash, m_size); + + m_hash ^= m_hash >> 13; + m_hash *= MURMUR_M; + m_hash ^= m_hash >> 15; + + return m_hash; + } + + inline void HashMurmur2A::readUnaligned(const void* _data, uint32_t& _out) + { + const uint8_t* data = (const uint8_t*)_data; + if (BX_ENABLED(BX_CPU_ENDIAN_BIG) ) + { + _out = 0 + | data[0]<<24 + | data[1]<<16 + | data[2]<<8 + | data[3] + ; + } + else + { + _out = 0 + | data[0] + | data[1]<<8 + | data[2]<<16 + | data[3]<<24 + ; + } + } + + inline void HashMurmur2A::mixTail(const uint8_t*& _data, int& _len) + { + while( _len && ((_len<4) || m_count) ) + { + m_tail |= (*_data++) << (m_count * 8); + + m_count++; + _len--; + + if(m_count == 4) + { + mmix(m_hash, m_tail); + m_tail = 0; + m_count = 0; + } + } + } + +#undef MURMUR_M +#undef MURMUR_R +#undef mmix + + inline uint32_t hashMurmur2A(const void* _data, uint32_t _size) + { + HashMurmur2A murmur; + murmur.begin(); + murmur.add(_data, (int)_size); + return murmur.end(); + } + + template <typename Ty> + inline uint32_t hashMurmur2A(const Ty& _data) + { + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + return hashMurmur2A(&_data, sizeof(Ty) ); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/mutex.h b/3rdparty/bx/include/bx/mutex.h index 76a02e1a7e8..777e577b950 100644 --- a/3rdparty/bx/include/bx/mutex.h +++ b/3rdparty/bx/include/bx/mutex.h @@ -13,52 +13,18 @@ #if BX_CONFIG_SUPPORTS_THREADING -#if BX_PLATFORM_NACL || BX_PLATFORM_LINUX || BX_PLATFORM_ANDROID || BX_PLATFORM_OSX +#if 0 \ + || BX_PLATFORM_ANDROID \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_OSX # include <pthread.h> -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_WINRT -# include <errno.h> -#endif // BX_PLATFORM_ +#endif // namespace bx { -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - typedef CRITICAL_SECTION pthread_mutex_t; - typedef unsigned pthread_mutexattr_t; - - inline int pthread_mutex_lock(pthread_mutex_t* _mutex) - { - EnterCriticalSection(_mutex); - return 0; - } - - inline int pthread_mutex_unlock(pthread_mutex_t* _mutex) - { - LeaveCriticalSection(_mutex); - return 0; - } - - inline int pthread_mutex_trylock(pthread_mutex_t* _mutex) - { - return TryEnterCriticalSection(_mutex) ? 0 : EBUSY; - } - - inline int pthread_mutex_init(pthread_mutex_t* _mutex, pthread_mutexattr_t* /*_attr*/) - { -#if BX_PLATFORM_WINRT - InitializeCriticalSectionEx(_mutex, 4000, 0); // docs recommend 4000 spincount as sane default -#else - InitializeCriticalSection(_mutex); -#endif - return 0; - } - - inline int pthread_mutex_destroy(pthread_mutex_t* _mutex) - { - DeleteCriticalSection(_mutex); - return 0; - } -#endif // BX_PLATFORM_ - + /// class Mutex { BX_CLASS(Mutex @@ -67,36 +33,27 @@ namespace bx ); public: - Mutex() - { - pthread_mutexattr_t attr; -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT -#else - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); -#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_WINRT - pthread_mutex_init(&m_handle, &attr); - } - - ~Mutex() - { - pthread_mutex_destroy(&m_handle); - } - - void lock() - { - pthread_mutex_lock(&m_handle); - } - - void unlock() - { - pthread_mutex_unlock(&m_handle); - } + /// + Mutex(); + + /// + ~Mutex(); + + /// + void lock(); + + /// + void unlock(); private: +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + CRITICAL_SECTION m_handle; +#else pthread_mutex_t m_handle; +#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT }; + /// class MutexScope { BX_CLASS(MutexScope @@ -106,16 +63,11 @@ namespace bx ); public: - MutexScope(Mutex& _mutex) - : m_mutex(_mutex) - { - m_mutex.lock(); - } + /// + MutexScope(Mutex& _mutex); - ~MutexScope() - { - m_mutex.unlock(); - } + /// + ~MutexScope(); private: Mutex& m_mutex; @@ -123,6 +75,7 @@ namespace bx typedef Mutex LwMutex; + /// class LwMutexScope { BX_CLASS(LwMutexScope @@ -132,16 +85,11 @@ namespace bx ); public: - LwMutexScope(LwMutex& _mutex) - : m_mutex(_mutex) - { - m_mutex.lock(); - } + /// + LwMutexScope(LwMutex& _mutex); - ~LwMutexScope() - { - m_mutex.unlock(); - } + /// + ~LwMutexScope(); private: LwMutex& m_mutex; @@ -149,6 +97,8 @@ namespace bx } // namespace bx +#include "mutex.inl" + #endif // BX_CONFIG_SUPPORTS_THREADING #endif // BX_MUTEX_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/mutex.inl b/3rdparty/bx/include/bx/mutex.inl new file mode 100644 index 00000000000..0d4140208e1 --- /dev/null +++ b/3rdparty/bx/include/bx/mutex.inl @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_MUTEX_H_HEADER_GUARD +# error "Must be included from bx/mutex.h!" +#endif // BX_MUTEX_H_HEADER_GUARD + +namespace bx +{ + inline MutexScope::MutexScope(Mutex& _mutex) + : m_mutex(_mutex) + { + m_mutex.lock(); + } + + inline MutexScope::~MutexScope() + { + m_mutex.unlock(); + } + + inline LwMutexScope::LwMutexScope(LwMutex& _mutex) + : m_mutex(_mutex) + { + m_mutex.lock(); + } + + inline LwMutexScope::~LwMutexScope() + { + m_mutex.unlock(); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/os.h b/3rdparty/bx/include/bx/os.h index 78349ddab4b..d2639756198 100644 --- a/3rdparty/bx/include/bx/os.h +++ b/3rdparty/bx/include/bx/os.h @@ -10,57 +10,6 @@ #include "debug.h" #include <sys/stat.h> -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT -# include <windows.h> -# include <psapi.h> -#elif BX_PLATFORM_ANDROID \ - || BX_PLATFORM_EMSCRIPTEN \ - || BX_PLATFORM_BSD \ - || BX_PLATFORM_HURD \ - || BX_PLATFORM_IOS \ - || BX_PLATFORM_LINUX \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_OSX \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK -# include <sched.h> // sched_yield -# if BX_PLATFORM_BSD \ - || BX_PLATFORM_IOS \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_OSX \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_STEAMLINK -# include <pthread.h> // mach_port_t -# endif // BX_PLATFORM_* - -# include <time.h> // nanosleep -# if !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL -# include <dlfcn.h> // dlopen, dlclose, dlsym -# endif // !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL - -# if BX_PLATFORM_ANDROID -# include <malloc.h> // mallinfo -# elif BX_PLATFORM_LINUX \ - || BX_PLATFORM_RPI \ - || BX_PLATFORM_STEAMLINK -# include <unistd.h> // syscall -# include <sys/syscall.h> -# elif BX_PLATFORM_OSX -# include <mach/mach.h> // mach_task_basic_info -# elif BX_PLATFORM_HURD -# include <pthread/pthread.h> // pthread_self -# elif BX_PLATFORM_ANDROID -# include "debug.h" // getTid is not implemented... -# endif // BX_PLATFORM_ANDROID -#endif // BX_PLATFORM_ - -#if BX_CRT_MSVC -# include <direct.h> // _getcwd -#else -# include <unistd.h> // getcwd -#endif // BX_CRT_MSVC - #if BX_PLATFORM_OSX # define BX_DL_EXT "dylib" #elif BX_PLATFORM_WINDOWS @@ -71,241 +20,6 @@ namespace bx { - inline void sleep(uint32_t _ms) - { -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 - ::Sleep(_ms); -#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - BX_UNUSED(_ms); - debugOutput("sleep is not implemented"); debugBreak(); -#else - timespec req = {(time_t)_ms/1000, (long)((_ms%1000)*1000000)}; - timespec rem = {0, 0}; - ::nanosleep(&req, &rem); -#endif // BX_PLATFORM_ - } - - inline void yield() - { -#if BX_PLATFORM_WINDOWS - ::SwitchToThread(); -#elif BX_PLATFORM_XBOX360 - ::Sleep(0); -#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - debugOutput("yield is not implemented"); debugBreak(); -#else - ::sched_yield(); -#endif // BX_PLATFORM_ - } - - inline uint32_t getTid() - { -#if BX_PLATFORM_WINDOWS - return ::GetCurrentThreadId(); -#elif BX_PLATFORM_LINUX || BX_PLATFORM_RPI || BX_PLATFORM_STEAMLINK - return (pid_t)::syscall(SYS_gettid); -#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX - return (mach_port_t)::pthread_mach_thread_np(pthread_self() ); -#elif BX_PLATFORM_BSD || BX_PLATFORM_NACL - // Casting __nc_basic_thread_data*... need better way to do this. - return *(uint32_t*)::pthread_self(); -#elif BX_PLATFORM_HURD - return (pthread_t)::pthread_self(); -#else -//# pragma message "not implemented." - debugOutput("getTid is not implemented"); debugBreak(); - return 0; -#endif // - } - - inline size_t getProcessMemoryUsed() - { -#if BX_PLATFORM_ANDROID - struct mallinfo mi = mallinfo(); - return mi.uordblks; -#elif BX_PLATFORM_LINUX || BX_PLATFORM_HURD - FILE* file = fopen("/proc/self/statm", "r"); - if (NULL == file) - { - return 0; - } - - long pages = 0; - int items = fscanf(file, "%*s%ld", &pages); - fclose(file); - return 1 == items - ? pages * sysconf(_SC_PAGESIZE) - : 0 - ; -#elif BX_PLATFORM_OSX -# if defined(MACH_TASK_BASIC_INFO) - mach_task_basic_info info; - mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; - - int const result = task_info(mach_task_self() - , MACH_TASK_BASIC_INFO - , (task_info_t)&info - , &infoCount - ); -# else // MACH_TASK_BASIC_INFO - task_basic_info info; - mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT; - - int const result = task_info(mach_task_self() - , TASK_BASIC_INFO - , (task_info_t)&info - , &infoCount - ); -# endif // MACH_TASK_BASIC_INFO - if (KERN_SUCCESS != result) - { - return 0; - } - - return info.resident_size; -#elif BX_PLATFORM_WINDOWS - PROCESS_MEMORY_COUNTERS pmc; - GetProcessMemoryInfo(GetCurrentProcess() - , &pmc - , sizeof(pmc) - ); - return pmc.WorkingSetSize; -#else - return 0; -#endif // BX_PLATFORM_* - } - - inline void* dlopen(const char* _filePath) - { -#if BX_PLATFORM_WINDOWS - return (void*)::LoadLibraryA(_filePath); -#elif BX_PLATFORM_EMSCRIPTEN \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_filePath); - return NULL; -#else - return ::dlopen(_filePath, RTLD_LOCAL|RTLD_LAZY); -#endif // BX_PLATFORM_ - } - - inline void dlclose(void* _handle) - { -#if BX_PLATFORM_WINDOWS - ::FreeLibrary( (HMODULE)_handle); -#elif BX_PLATFORM_EMSCRIPTEN \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_handle); -#else - ::dlclose(_handle); -#endif // BX_PLATFORM_ - } - - inline void* dlsym(void* _handle, const char* _symbol) - { -#if BX_PLATFORM_WINDOWS - return (void*)::GetProcAddress( (HMODULE)_handle, _symbol); -#elif BX_PLATFORM_EMSCRIPTEN \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_handle, _symbol); - return NULL; -#else - return ::dlsym(_handle, _symbol); -#endif // BX_PLATFORM_ - } - - inline bool getenv(const char* _name, char* _out, uint32_t* _inOutSize) - { -#if BX_PLATFORM_WINDOWS - DWORD len = ::GetEnvironmentVariableA(_name, _out, *_inOutSize); - bool result = len != 0 && len < *_inOutSize; - *_inOutSize = len; - return result; -#elif BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_name, _out, _inOutSize); - return false; -#else - const char* ptr = ::getenv(_name); - uint32_t len = 0; - if (NULL != ptr) - { - len = (uint32_t)strlen(ptr); - } - bool result = len != 0 && len < *_inOutSize; - if (len < *_inOutSize) - { - strcpy(_out, ptr); - } - - *_inOutSize = len; - return result; -#endif // BX_PLATFORM_ - } - - inline void setenv(const char* _name, const char* _value) - { -#if BX_PLATFORM_WINDOWS - ::SetEnvironmentVariableA(_name, _value); -#elif BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_name, _value); -#else - ::setenv(_name, _value, 1); -#endif // BX_PLATFORM_ - } - - inline void unsetenv(const char* _name) - { -#if BX_PLATFORM_WINDOWS - ::SetEnvironmentVariableA(_name, NULL); -#elif BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_name); -#else - ::unsetenv(_name); -#endif // BX_PLATFORM_ - } - - inline int chdir(const char* _path) - { -#if BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_path); - return -1; -#elif BX_CRT_MSVC - return ::_chdir(_path); -#else - return ::chdir(_path); -#endif // BX_COMPILER_ - } - - inline char* pwd(char* _buffer, uint32_t _size) - { -#if BX_PLATFORM_PS4 \ - || BX_PLATFORM_XBOXONE \ - || BX_PLATFORM_WINRT - BX_UNUSED(_buffer, _size); - return NULL; -#elif BX_CRT_MSVC - return ::_getcwd(_buffer, (int)_size); -#else - return ::getcwd(_buffer, _size); -#endif // BX_COMPILER_ - } - struct FileInfo { enum Enum @@ -320,50 +34,50 @@ namespace bx Enum m_type; }; - inline bool stat(const char* _filePath, FileInfo& _fileInfo) - { - _fileInfo.m_size = 0; - _fileInfo.m_type = FileInfo::Count; + /// + void sleep(uint32_t _ms); -#if BX_COMPILER_MSVC - struct ::_stat64 st; - int32_t result = ::_stat64(_filePath, &st); + /// + void yield(); - if (0 != result) - { - return false; - } + /// + uint32_t getTid(); - if (0 != (st.st_mode & _S_IFREG) ) - { - _fileInfo.m_type = FileInfo::Regular; - } - else if (0 != (st.st_mode & _S_IFDIR) ) - { - _fileInfo.m_type = FileInfo::Directory; - } -#else - struct ::stat st; - int32_t result = ::stat(_filePath, &st); - if (0 != result) - { - return false; - } + /// + size_t getProcessMemoryUsed(); - if (0 != (st.st_mode & S_IFREG) ) - { - _fileInfo.m_type = FileInfo::Regular; - } - else if (0 != (st.st_mode & S_IFDIR) ) - { - _fileInfo.m_type = FileInfo::Directory; - } -#endif // BX_COMPILER_MSVC + /// + void* dlopen(const char* _filePath); + + /// + void dlclose(void* _handle); + + /// + void* dlsym(void* _handle, const char* _symbol); + + /// + bool getenv(const char* _name, char* _out, uint32_t* _inOutSize); + + /// + void setenv(const char* _name, const char* _value); + + /// + void unsetenv(const char* _name); + + /// + int chdir(const char* _path); + + /// + char* pwd(char* _buffer, uint32_t _size); + + /// + bool getTempPath(char* _out, uint32_t* _inOutSize); - _fileInfo.m_size = st.st_size; + /// + bool stat(const char* _filePath, FileInfo& _fileInfo); - return true; - } + /// + void* exec(const char* const* _argv); } // namespace bx diff --git a/3rdparty/bx/include/bx/pixelformat.h b/3rdparty/bx/include/bx/pixelformat.h new file mode 100644 index 00000000000..5b2bf565803 --- /dev/null +++ b/3rdparty/bx/include/bx/pixelformat.h @@ -0,0 +1,243 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_PIXEL_FORMAT_H_HEADER_GUARD +#define BX_PIXEL_FORMAT_H_HEADER_GUARD + +#include <bx/fpumath.h> +#include <bx/uint32_t.h> + +namespace bx +{ + struct EncodingType + { + enum Enum + { + Unorm, + Int, + Uint, + Float, + Snorm, + + Count + }; + }; + + typedef void (*PackFn)(void*, const float*); + typedef void (*UnpackFn)(float*, const void*); + + /// + uint32_t toUnorm(float _value, float _scale); + + /// + float fromUnorm(uint32_t _value, float _scale); + + /// + int32_t toSnorm(float _value, float _scale); + + /// + float fromSnorm(int32_t _value, float _scale); + + // R8 + void packR8(void* _dst, const float* _src); + void unpackR8(float* _dst, const void* _src); + + // R8S + void packR8S(void* _dst, const float* _src); + void unpackR8S(float* _dst, const void* _src); + + // R8I + void packR8I(void* _dst, const float* _src); + void unpackR8I(float* _dst, const void* _src); + + // R8U + void packR8U(void* _dst, const float* _src); + void unpackR8U(float* _dst, const void* _src); + + // RG8 + void packRg8(void* _dst, const float* _src); + void unpackRg8(float* _dst, const void* _src); + + // RG8S + void packRg8S(void* _dst, const float* _src); + void unpackRg8S(float* _dst, const void* _src); + + // RG8I + void packRg8I(void* _dst, const float* _src); + void unpackRg8I(float* _dst, const void* _src); + + // RG8U + void packRg8U(void* _dst, const float* _src); + void unpackRg8U(float* _dst, const void* _src); + + // RGB8 + void packRgb8(void* _dst, const float* _src); + void unpackRgb8(float* _dst, const void* _src); + + // RGB8S + void packRgb8S(void* _dst, const float* _src); + void unpackRgb8S(float* _dst, const void* _src); + + // RGB8I + void packRgb8I(void* _dst, const float* _src); + void unpackRgb8I(float* _dst, const void* _src); + + // RGB8U + void packRgb8U(void* _dst, const float* _src); + void unpackRgb8U(float* _dst, const void* _src); + + // RGBA8 + void packRgba8(void* _dst, const float* _src); + void unpackRgba8(float* _dst, const void* _src); + + // BGRA8 + void packBgra8(void* _dst, const float* _src); + void unpackBgra8(float* _dst, const void* _src); + + // RGBA8S + void packRgba8S(void* _dst, const float* _src); + void unpackRgba8S(float* _dst, const void* _src); + + // RGBA8I + void packRgba8I(void* _dst, const float* _src); + void unpackRgba8I(float* _dst, const void* _src); + + // RGBA8U + void packRgba8U(void* _dst, const float* _src); + void unpackRgba8U(float* _dst, const void* _src); + + // R16 + void packR16(void* _dst, const float* _src); + void unpackR16(float* _dst, const void* _src); + + // R16S + void packR16S(void* _dst, const float* _src); + void unpackR16S(float* _dst, const void* _src); + + // R16I + void packR16I(void* _dst, const float* _src); + void unpackR16I(float* _dst, const void* _src); + + // R16U + void packR16U(void* _dst, const float* _src); + void unpackR16U(float* _dst, const void* _src); + + // R16F + void packR16F(void* _dst, const float* _src); + void unpackR16F(float* _dst, const void* _src); + + // RG16 + void packRg16(void* _dst, const float* _src); + void unpackRg16(float* _dst, const void* _src); + + // RG16S + void packRg16S(void* _dst, const float* _src); + void unpackRg16S(float* _dst, const void* _src); + + // RG16I + void packRg16I(void* _dst, const float* _src); + void unpackRg16I(float* _dst, const void* _src); + + // RG16U + void packRg16U(void* _dst, const float* _src); + void unpackRg16U(float* _dst, const void* _src); + + // RG16F + void packRg16F(void* _dst, const float* _src); + void unpackRg16F(float* _dst, const void* _src); + + // RGBA16 + void packRgba16(void* _dst, const float* _src); + void unpackRgba16(float* _dst, const void* _src); + + // RGBA16S + void packRgba16S(void* _dst, const float* _src); + void unpackRgba16S(float* _dst, const void* _src); + + // RGBA16I + void packRgba16I(void* _dst, const float* _src); + void unpackRgba16I(float* _dst, const void* _src); + + // RGBA16U + void packRgba16U(void* _dst, const float* _src); + void unpackRgba16U(float* _dst, const void* _src); + + // RGBA16F + void packRgba16F(void* _dst, const float* _src); + void unpackRgba16F(float* _dst, const void* _src); + + // R32I + void packR32I(void* _dst, const float* _src); + void unpackR32I(float* _dst, const void* _src); + + // R32U + void packR32U(void* _dst, const float* _src); + void unpackR32U(float* _dst, const void* _src); + + // R32F + void packR32F(void* _dst, const float* _src); + void unpackR32F(float* _dst, const void* _src); + + // RG32I + void packRg32I(void* _dst, const float* _src); + void unpackRg32I(float* _dst, const void* _src); + + // RG32U + void packRg32U(void* _dst, const float* _src); + void unpackRg32U(float* _dst, const void* _src); + + // RGB9E5F + void packRgb9E5F(void* _dst, const float* _src); + void unpackRgb9E5F(float* _dst, const void* _src); + + // RGBA32I + void packRgba32I(void* _dst, const float* _src); + void unpackRgba32I(float* _dst, const void* _src); + + // RGBA32U + void packRgba32U(void* _dst, const float* _src); + void unpackRgba32U(float* _dst, const void* _src); + + // RGBA32F + void packRgba32F(void* _dst, const float* _src); + void unpackRgba32F(float* _dst, const void* _src); + + // R5G6B5 + void packR5G6B5(void* _dst, const float* _src); + void unpackR5G6B5(float* _dst, const void* _src); + + // RGBA4 + void packRgba4(void* _dst, const float* _src); + void unpackRgba4(float* _dst, const void* _src); + + // RGBA4 + void packBgra4(void* _dst, const float* _src); + void unpackBgra4(float* _dst, const void* _src); + + // RGB5A1 + void packRgb5a1(void* _dst, const float* _src); + void unpackRgb5a1(float* _dst, const void* _src); + + // BGR5A1 + void packBgr5a1(void* _dst, const float* _src); + void unpackBgr5a1(float* _dst, const void* _src); + + // RGB10A2 + void packRgb10A2(void* _dst, const float* _src); + void unpackRgb10A2(float* _dst, const void* _src); + + // R11G11B10F + void packR11G11B10F(void* _dst, const float* _src); + void unpackR11G11B10F(float* _dst, const void* _src); + + // RG32F + void packRg32F(void* _dst, const float* _src); + void unpackRg32F(float* _dst, const void* _src); + +} // namespace bx + +#include "pixelformat.inl" + +#endif // BX_PIXEL_FORMAT_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/pixelformat.inl b/3rdparty/bx/include/bx/pixelformat.inl new file mode 100644 index 00000000000..be48c85d931 --- /dev/null +++ b/3rdparty/bx/include/bx/pixelformat.inl @@ -0,0 +1,945 @@ +/* + * Copyright 2010-2016 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_PIXEL_FORMAT_H_HEADER_GUARD +# error "Must be included from bx/pixelformat.h" +#endif // BX_PIXEL_FORMAT_H_HEADER_GUARD + +namespace bx +{ + inline uint32_t toUnorm(float _value, float _scale) + { + return uint32_t(fround(fsaturate(_value) * _scale) ); + } + + inline float fromUnorm(uint32_t _value, float _scale) + { + return float(_value) / _scale; + } + + inline int32_t toSnorm(float _value, float _scale) + { + return int32_t(fround( + fclamp(_value, -1.0f, 1.0f) * _scale) + ); + } + + inline float fromSnorm(int32_t _value, float _scale) + { + return fmax(-1.0f, float(_value) / _scale); + } + + // R8 + inline void packR8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(toUnorm(_src[0], 255.0f) ); + } + + inline void unpackR8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = fromUnorm(src[0], 255.0f); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R8S + inline void packR8S(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(toSnorm(_src[0], 127.0f) ); + } + + inline void unpackR8S(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = fromSnorm(src[0], 127.0f); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R8I + inline void packR8I(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(_src[0]); + } + + inline void unpackR8I(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R8U + inline void packR8U(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(_src[0]); + } + + inline void unpackR8U(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG8 + inline void packRg8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(toUnorm(_src[0], 255.0f) ); + dst[1] = uint8_t(toUnorm(_src[1], 255.0f) ); + } + + inline void unpackRg8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = fromUnorm(src[0], 255.0f); + _dst[1] = fromUnorm(src[1], 255.0f); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG8S + inline void packRg8S(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(toSnorm(_src[0], 127.0f) ); + dst[1] = int8_t(toSnorm(_src[1], 127.0f) ); + } + + inline void unpackRg8S(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = fromSnorm(src[0], 127.0f); + _dst[1] = fromSnorm(src[1], 127.0f); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG8I + inline void packRg8I(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(_src[0]); + dst[1] = int8_t(_src[1]); + } + + inline void unpackRg8I(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG8U + inline void packRg8U(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(_src[0]); + dst[1] = uint8_t(_src[1]); + } + + inline void unpackRg8U(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RGB8 + inline void packRgb8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(toUnorm(_src[0], 255.0f) ); + dst[1] = uint8_t(toUnorm(_src[1], 255.0f) ); + dst[2] = uint8_t(toUnorm(_src[2], 255.0f) ); + } + + inline void unpackRgb8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = fromUnorm(src[0], 255.0f); + _dst[1] = fromUnorm(src[1], 255.0f); + _dst[2] = fromUnorm(src[2], 255.0f); + _dst[3] = 1.0f; + } + + // RGB8S + inline void packRgb8S(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(toSnorm(_src[0], 127.0f) ); + dst[1] = int8_t(toSnorm(_src[1], 127.0f) ); + dst[2] = int8_t(toSnorm(_src[2], 127.0f) ); + } + + inline void unpackRgb8S(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = fromSnorm(src[0], 127.0f); + _dst[1] = fromSnorm(src[1], 127.0f); + _dst[2] = fromSnorm(src[2], 127.0f); + _dst[3] = 1.0f; + } + + // RGB8I + inline void packRgb8I(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(_src[0]); + dst[1] = int8_t(_src[1]); + dst[2] = int8_t(_src[2]); + } + + inline void unpackRgb8I(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = 1.0f; + } + + // RGB8U + inline void packRgb8U(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(_src[0]); + dst[1] = uint8_t(_src[1]); + dst[2] = uint8_t(_src[2]); + } + + inline void unpackRgb8U(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = 1.0f; + } + + // BGRA8 + inline void packBgra8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[2] = uint8_t(toUnorm(_src[0], 255.0f) ); + dst[1] = uint8_t(toUnorm(_src[1], 255.0f) ); + dst[0] = uint8_t(toUnorm(_src[2], 255.0f) ); + dst[3] = uint8_t(toUnorm(_src[3], 255.0f) ); + } + + inline void unpackBgra8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = fromUnorm(src[2], 255.0f); + _dst[1] = fromUnorm(src[1], 255.0f); + _dst[2] = fromUnorm(src[0], 255.0f); + _dst[3] = fromUnorm(src[3], 255.0f); + } + + // RGBA8 + inline void packRgba8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(toUnorm(_src[0], 255.0f) ); + dst[1] = uint8_t(toUnorm(_src[1], 255.0f) ); + dst[2] = uint8_t(toUnorm(_src[2], 255.0f) ); + dst[3] = uint8_t(toUnorm(_src[3], 255.0f) ); + } + + inline void unpackRgba8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = fromUnorm(src[0], 255.0f); + _dst[1] = fromUnorm(src[1], 255.0f); + _dst[2] = fromUnorm(src[2], 255.0f); + _dst[3] = fromUnorm(src[3], 255.0f); + } + + // RGBA8S + inline void packRgba8S(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(toSnorm(_src[0], 127.0f) ); + dst[1] = int8_t(toSnorm(_src[1], 127.0f) ); + dst[2] = int8_t(toSnorm(_src[2], 127.0f) ); + dst[3] = int8_t(toSnorm(_src[3], 127.0f) ); + } + + inline void unpackRgba8S(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = fromSnorm(src[0], 127.0f); + _dst[1] = fromSnorm(src[1], 127.0f); + _dst[2] = fromSnorm(src[2], 127.0f); + _dst[3] = fromSnorm(src[3], 127.0f); + } + + // RGBA8I + inline void packRgba8I(void* _dst, const float* _src) + { + int8_t* dst = (int8_t*)_dst; + dst[0] = int8_t(_src[0]); + dst[1] = int8_t(_src[1]); + dst[2] = int8_t(_src[2]); + dst[3] = int8_t(_src[3]); + } + + inline void unpackRgba8I(float* _dst, const void* _src) + { + const int8_t* src = (const int8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = float(src[3]); + } + + // RGBA8U + inline void packRgba8U(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + dst[0] = uint8_t(_src[0]); + dst[1] = uint8_t(_src[1]); + dst[2] = uint8_t(_src[2]); + dst[3] = uint8_t(_src[3]); + } + + inline void unpackRgba8U(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = float(src[3]); + } + + // R16 + inline void packR16(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) ); + } + + inline void unpackR16(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = fromUnorm(src[0], 65535.0f); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R16S + inline void packR16S(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(toSnorm(_src[0], 32767.0f) ); + } + + inline void unpackR16S(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = fromSnorm(src[0], 32767.0f); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R16I + inline void packR16I(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(_src[0]); + } + + inline void unpackR16I(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R16U + inline void packR16U(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(_src[0]); + } + + inline void unpackR16U(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = float(src[0]); + } + + // R16F + inline void packR16F(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = halfFromFloat(_src[0]); + } + + inline void unpackR16F(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = halfToFloat(src[0]); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG16 + inline void packRg16(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) ); + dst[1] = uint16_t(toUnorm(_src[1], 65535.0f) ); + } + + inline void unpackRg16(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = fromUnorm(src[0], 65535.0f); + _dst[1] = fromUnorm(src[1], 65535.0f); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG16S + inline void packRg16S(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(toSnorm(_src[0], 32767.0f) ); + dst[1] = int16_t(toSnorm(_src[1], 32767.0f) ); + } + + inline void unpackRg16S(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = fromSnorm(src[0], 32767.0f); + _dst[1] = fromSnorm(src[1], 32767.0f); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG16I + inline void packRg16I(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(_src[0]); + dst[1] = int16_t(_src[1]); + } + + inline void unpackRg16I(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG16U + inline void packRg16U(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(_src[0]); + dst[1] = uint16_t(_src[1]); + } + + inline void unpackRg16U(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RG16F + inline void packRg16F(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = halfFromFloat(_src[0]); + dst[1] = halfFromFloat(_src[1]); + } + + inline void unpackRg16F(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = halfToFloat(src[0]); + _dst[1] = halfToFloat(src[1]); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // RGBA16 + inline void packRgba16(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) ); + dst[1] = uint16_t(toUnorm(_src[1], 65535.0f) ); + dst[2] = uint16_t(toUnorm(_src[2], 65535.0f) ); + dst[3] = uint16_t(toUnorm(_src[3], 65535.0f) ); + } + + inline void unpackRgba16(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = fromUnorm(src[0], 65535.0f); + _dst[1] = fromUnorm(src[1], 65535.0f); + _dst[2] = fromUnorm(src[2], 65535.0f); + _dst[3] = fromUnorm(src[3], 65535.0f); + } + + // RGBA16S + inline void packRgba16S(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(toSnorm(_src[0], 32767.0f) ); + dst[1] = int16_t(toSnorm(_src[1], 32767.0f) ); + dst[2] = int16_t(toSnorm(_src[2], 32767.0f) ); + dst[3] = int16_t(toSnorm(_src[3], 32767.0f) ); + } + + inline void unpackRgba16S(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = fromSnorm(src[0], 32767.0f); + _dst[1] = fromSnorm(src[1], 32767.0f); + _dst[2] = fromSnorm(src[2], 32767.0f); + _dst[3] = fromSnorm(src[3], 32767.0f); + } + + // RGBA16I + inline void packRgba16I(void* _dst, const float* _src) + { + int16_t* dst = (int16_t*)_dst; + dst[0] = int16_t(_src[0]); + dst[1] = int16_t(_src[1]); + dst[2] = int16_t(_src[2]); + dst[3] = int16_t(_src[3]); + } + + inline void unpackRgba16I(float* _dst, const void* _src) + { + const int16_t* src = (const int16_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = float(src[3]); + } + + // RGBA16U + inline void packRgba16U(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = uint16_t(_src[0]); + dst[1] = uint16_t(_src[1]); + dst[2] = uint16_t(_src[2]); + dst[3] = uint16_t(_src[3]); + } + + inline void unpackRgba16U(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = float(src[0]); + _dst[1] = float(src[1]); + _dst[2] = float(src[2]); + _dst[3] = float(src[3]); + } + + // RGBA16F + inline void packRgba16F(void* _dst, const float* _src) + { + uint16_t* dst = (uint16_t*)_dst; + dst[0] = halfFromFloat(_src[0]); + dst[1] = halfFromFloat(_src[1]); + dst[2] = halfFromFloat(_src[2]); + dst[3] = halfFromFloat(_src[3]); + } + + inline void unpackRgba16F(float* _dst, const void* _src) + { + const uint16_t* src = (const uint16_t*)_src; + _dst[0] = halfToFloat(src[0]); + _dst[1] = halfToFloat(src[1]); + _dst[2] = halfToFloat(src[2]); + _dst[3] = halfToFloat(src[3]); + } + + // R24 + inline void packR24(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + const uint32_t rr = uint32_t(toUnorm(_src[0], 16777216.0f) ); + dst[0] = uint8_t(rr ); + dst[1] = uint8_t(rr>> 8); + dst[2] = uint8_t(rr>>16); + } + + inline void unpackR24(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + const uint32_t rr = 0 + | (src[0] ) + | (src[1]<< 8) + | (src[2]<<16) + ; + + _dst[0] = fromUnorm(rr, 16777216.0f); + _dst[1] = 0.0f; + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R24G8 + inline void packR24G8(void* _dst, const float* _src) + { + uint8_t* dst = (uint8_t*)_dst; + const uint32_t rr = uint32_t(toUnorm(_src[0], 16777216.0f) ); + dst[0] = uint8_t(rr ); + dst[1] = uint8_t(rr>> 8); + dst[2] = uint8_t(rr>>16); + dst[3] = uint8_t(toUnorm(_src[1], 255.0f) ); + } + + inline void unpackR24G8(float* _dst, const void* _src) + { + const uint8_t* src = (const uint8_t*)_src; + const uint32_t rr = 0 + | (src[0] ) + | (src[1]<< 8) + | (src[2]<<16) + ; + + _dst[0] = fromUnorm(rr, 16777216.0f); + _dst[1] = fromUnorm(src[3], 255.0f); + _dst[2] = 0.0f; + _dst[3] = 1.0f; + } + + // R32I + inline void packR32I(void* _dst, const float* _src) + { + memcpy(_dst, _src, 4); + } + + inline void unpackR32I(float* _dst, const void* _src) + { + memcpy(_dst, _src, 4); + } + + // R32U + inline void packR32U(void* _dst, const float* _src) + { + memcpy(_dst, _src, 4); + } + + inline void unpackR32U(float* _dst, const void* _src) + { + memcpy(_dst, _src, 4); + } + + // R32F + inline void packR32F(void* _dst, const float* _src) + { + memcpy(_dst, _src, 4); + } + + inline void unpackR32F(float* _dst, const void* _src) + { + memcpy(_dst, _src, 4); + } + + // RG32I + inline void packRg32I(void* _dst, const float* _src) + { + memcpy(_dst, _src, 8); + } + + inline void unpackRg32I(float* _dst, const void* _src) + { + memcpy(_dst, _src, 8); + } + + // RG32U + inline void packRg32U(void* _dst, const float* _src) + { + memcpy(_dst, _src, 8); + } + + inline void unpackRg32U(float* _dst, const void* _src) + { + memcpy(_dst, _src, 8); + } + + // RG32F + inline void packRg32F(void* _dst, const float* _src) + { + memcpy(_dst, _src, 8); + } + + inline void unpackRg32F(float* _dst, const void* _src) + { + memcpy(_dst, _src, 8); + } + + template<int32_t MantissaBits, int32_t ExpBits> + inline void encodeRgbE(float* _dst, const float* _src) + { + // Reference: + // https://www.opengl.org/registry/specs/EXT/texture_shared_exponent.txt + const int32_t expMax = (1<<ExpBits) - 1; + const int32_t expBias = (1<<(ExpBits - 1) ) - 1; + const float sharedExpMax = float(expMax) / float(expMax + 1) * float(1 << (expMax - expBias) ); + + const float rr = fclamp(_src[0], 0.0f, sharedExpMax); + const float gg = fclamp(_src[1], 0.0f, sharedExpMax); + const float bb = fclamp(_src[2], 0.0f, sharedExpMax); + const float max = fmax3(rr, gg, bb); + union { float ff; uint32_t ui; } cast = { max }; + int32_t expShared = int32_t(uint32_imax(uint32_t(-expBias-1), ( ( (cast.ui>>23) & 0xff) - 127) ) ) + 1 + expBias; + float denom = fpow(2.0f, float(expShared - expBias - MantissaBits) ); + + if ( (1<<MantissaBits) == int32_t(fround(max/denom) ) ) + { + denom *= 2.0f; + ++expShared; + } + + const float invDenom = 1.0f/denom; + _dst[0] = fround(rr * invDenom); + _dst[1] = fround(gg * invDenom); + _dst[2] = fround(bb * invDenom); + _dst[3] = float(expShared); + } + + template<int32_t MantissaBits, int32_t ExpBits> + inline void decodeRgbE(float* _dst, const float* _src) + { + const int32_t expBias = (1<<(ExpBits - 1) ) - 1; + const float exponent = _src[3]-float(expBias-MantissaBits); + const float scale = fpow(2.0f, exponent); + _dst[0] = _src[0] * scale; + _dst[1] = _src[1] * scale; + _dst[2] = _src[2] * scale; + } + + // RGB9E5F + inline void packRgb9E5F(void* _dst, const float* _src) + { + float tmp[4]; + encodeRgbE<9, 5>(tmp, _src); + + *( (uint32_t*)_dst) = 0 + | (uint32_t(tmp[0]) ) + | (uint32_t(tmp[1]) << 9) + | (uint32_t(tmp[2]) <<18) + | (uint32_t(tmp[3]) <<27) + ; + } + + inline void unpackRgb9E5F(float* _dst, const void* _src) + { + uint32_t packed = *( (const uint32_t*)_src); + + float tmp[4]; + tmp[0] = float( ( (packed ) & 0x1ff) ) / 511.0f; + tmp[1] = float( ( (packed>> 9) & 0x1ff) ) / 511.0f; + tmp[2] = float( ( (packed>>18) & 0x1ff) ) / 511.0f; + tmp[3] = float( ( (packed>>27) & 0x1f) ); + + decodeRgbE<9, 5>(_dst, tmp); + } + + // RGBA32I + inline void packRgba32I(void* _dst, const float* _src) + { + memcpy(_dst, _src, 16); + } + + inline void unpackRgba32I(float* _dst, const void* _src) + { + memcpy(_dst, _src, 16); + } + + // RGBA32U + inline void packRgba32U(void* _dst, const float* _src) + { + memcpy(_dst, _src, 16); + } + + inline void unpackRgba32U(float* _dst, const void* _src) + { + memcpy(_dst, _src, 16); + } + + // RGBA32F + inline void packRgba32F(void* _dst, const float* _src) + { + memcpy(_dst, _src, 16); + } + + inline void unpackRgba32F(float* _dst, const void* _src) + { + memcpy(_dst, _src, 16); + } + + // R5G6B5 + inline void packR5G6B5(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 31.0f)<<11) + | uint16_t(toUnorm(_src[1], 63.0f)<< 5) + | uint16_t(toUnorm(_src[2], 31.0f) ) + ; + } + + inline void unpackR5G6B5(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed>>11) & 0x1f) ) / 31.0f; + _dst[1] = float( ( (packed>> 5) & 0x3f) ) / 63.0f; + _dst[2] = float( ( (packed ) & 0x1f) ) / 31.0f; + _dst[3] = 1.0f; + } + + // RGBA4 + inline void packRgba4(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 15.0f) ) + | uint16_t(toUnorm(_src[1], 15.0f)<< 4) + | uint16_t(toUnorm(_src[2], 15.0f)<< 8) + | uint16_t(toUnorm(_src[3], 15.0f)<<12) + ; + } + + inline void unpackRgba4(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed ) & 0xf) ) / 15.0f; + _dst[1] = float( ( (packed>> 4) & 0xf) ) / 15.0f; + _dst[2] = float( ( (packed>> 8) & 0xf) ) / 15.0f; + _dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f; + } + + // RGBA4 + inline void packBgra4(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 15.0f)<< 8) + | uint16_t(toUnorm(_src[1], 15.0f)<< 4) + | uint16_t(toUnorm(_src[2], 15.0f) ) + | uint16_t(toUnorm(_src[3], 15.0f)<<12) + ; + } + + inline void unpackBgra4(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed>> 8) & 0xf) ) / 15.0f; + _dst[1] = float( ( (packed>> 4) & 0xf) ) / 15.0f; + _dst[2] = float( ( (packed ) & 0xf) ) / 15.0f; + _dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f; + } + + // RGB5A1 + inline void packRgb5a1(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 31.0f) ) + | uint16_t(toUnorm(_src[1], 31.0f)<< 5) + | uint16_t(toUnorm(_src[2], 31.0f)<<10) + | uint16_t(toUnorm(_src[3], 1.0f)<<15) + ; + } + + inline void unpackRgb5a1(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed ) & 0x1f) ) / 31.0f; + _dst[1] = float( ( (packed>> 5) & 0x1f) ) / 31.0f; + _dst[2] = float( ( (packed>>10) & 0x1f) ) / 31.0f; + _dst[3] = float( ( (packed>>14) & 0x1) ); + } + + // BGR5A1 + inline void packBgr5a1(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 31.0f)<<10) + | uint16_t(toUnorm(_src[1], 31.0f)<< 5) + | uint16_t(toUnorm(_src[2], 31.0f) ) + | uint16_t(toUnorm(_src[3], 1.0f)<<15) + ; + } + + inline void unpackBgr5a1(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed>>10) & 0x1f) ) / 31.0f; + _dst[1] = float( ( (packed>> 5) & 0x1f) ) / 31.0f; + _dst[2] = float( ( (packed ) & 0x1f) ) / 31.0f; + _dst[3] = float( ( (packed>>14) & 0x1) ); + } + + // RGB10A2 + inline void packRgb10A2(void* _dst, const float* _src) + { + *( (uint32_t*)_dst) = 0 + | (toUnorm(_src[0], 1023.0f) ) + | (toUnorm(_src[1], 1023.0f)<<10) + | (toUnorm(_src[2], 1023.0f)<<20) + | (toUnorm(_src[3], 3.0f)<<30) + ; + } + + inline void unpackRgb10A2(float* _dst, const void* _src) + { + uint32_t packed = *( (const uint32_t*)_src); + _dst[0] = float( ( (packed ) & 0x3ff) ) / 1023.0f; + _dst[1] = float( ( (packed>>10) & 0x3ff) ) / 1023.0f; + _dst[2] = float( ( (packed>>20) & 0x3ff) ) / 1023.0f; + _dst[3] = float( ( (packed>>30) & 0x3) ) / 3.0f; + } + + // R11G11B10F + inline void packR11G11B10F(void* _dst, const float* _src) + { + *( (uint32_t*)_dst) = 0 + | ( (halfFromFloat(_src[0])>> 4) & 0x7ff) + | ( (halfFromFloat(_src[0])<< 7) & 0x3ff800) + | ( (halfFromFloat(_src[0])<<17) & 0xffc00000) + ; + } + + inline void unpackR11G11B10F(float* _dst, const void* _src) + { + uint32_t packed = *( (const uint32_t*)_src); + _dst[0] = halfToFloat( (packed<< 4) & 0x7ff0); + _dst[1] = halfToFloat( (packed>> 7) & 0x7ff0); + _dst[2] = halfToFloat( (packed>>17) & 0x7fe0); + _dst[3] = 1.0f; + } +} // namespace bx diff --git a/3rdparty/bx/include/bx/platform.h b/3rdparty/bx/include/bx/platform.h index e976732c031..99d29a037d9 100644 --- a/3rdparty/bx/include/bx/platform.h +++ b/3rdparty/bx/include/bx/platform.h @@ -31,6 +31,7 @@ // C Runtime #define BX_CRT_MSVC 0 #define BX_CRT_GLIBC 0 +#define BX_CRT_LIBCXX 0 #define BX_CRT_NEWLIB 0 #define BX_CRT_MINGW 0 #define BX_CRT_MUSL 0 @@ -68,7 +69,13 @@ # elif defined(__GLIBC__) # undef BX_CRT_GLIBC # define BX_CRT_GLIBC (__GLIBC__ * 10000 + __GLIBC_MINOR__ * 100) -# endif // defined(__GLIBC__) +# elif defined(__MINGW32__) || defined(__MINGW64__) +# undef BX_CRT_MINGW +# define BX_CRT_MINGW 1 +# elif defined(__apple_build_version__) || defined(__ANDROID__) +# undef BX_CRT_LIBCXX +# define BX_CRT_LIBCXX 1 +# endif // #elif defined(_MSC_VER) # undef BX_COMPILER_MSVC # define BX_COMPILER_MSVC _MSC_VER @@ -201,8 +208,7 @@ // RaspberryPi compiler defines __linux__ # undef BX_PLATFORM_RPI # define BX_PLATFORM_RPI 1 -#elif defined(__linux__) \ - || BX_CPU_RISCV +#elif defined(__linux__) # undef BX_PLATFORM_LINUX # define BX_PLATFORM_LINUX 1 #elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) \ @@ -231,24 +237,31 @@ #elif defined(__GNU__) # undef BX_PLATFORM_HURD # define BX_PLATFORM_HURD 1 -#else -# error "BX_PLATFORM_* is not defined!" #endif // -#define BX_PLATFORM_POSIX (0 \ - || BX_PLATFORM_ANDROID \ - || BX_PLATFORM_EMSCRIPTEN \ - || BX_PLATFORM_BSD \ - || BX_PLATFORM_HURD \ - || BX_PLATFORM_IOS \ - || BX_PLATFORM_LINUX \ - || BX_PLATFORM_NACL \ - || BX_PLATFORM_OSX \ - || BX_PLATFORM_QNX \ - || BX_PLATFORM_STEAMLINK \ - || BX_PLATFORM_PS4 \ - || BX_PLATFORM_RPI \ - ) +#define BX_PLATFORM_POSIX (0 \ + || BX_PLATFORM_ANDROID \ + || BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_HURD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_QNX \ + || BX_PLATFORM_STEAMLINK \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_RPI \ + ) + +#define BX_CRT_NONE !(0 \ + || BX_CRT_MSVC \ + || BX_CRT_GLIBC \ + || BX_CRT_LIBCXX \ + || BX_CRT_NEWLIB \ + || BX_CRT_MINGW \ + || BX_CRT_MUSL \ + ) #ifndef BX_CONFIG_ENABLE_MSVC_LEVEL4_WARNINGS # define BX_CONFIG_ENABLE_MSVC_LEVEL4_WARNINGS 0 @@ -319,6 +332,8 @@ # define BX_PLATFORM_NAME "Xbox 360" #elif BX_PLATFORM_XBOXONE # define BX_PLATFORM_NAME "Xbox One" +#else +# define BX_PLATFORM_NAME "None" #endif // BX_PLATFORM_ #if BX_CPU_ARM @@ -335,6 +350,20 @@ # define BX_CPU_NAME "x86" #endif // BX_CPU_ +#if BX_CRT_MSVC +# define BX_CRT_NAME "MSVC C Runtime" +#elif BX_CRT_GLIBC +# define BX_CRT_NAME "GNU C Library" +#elif BX_CRT_NEWLIB +# define BX_CRT_NAME "Newlib" +#elif BX_CRT_MINGW +# define BX_CRT_NAME "MinGW C Runtime" +#elif BX_CRT_MUSL +# define BX_CRT_NAME "musl libc" +#else +# define BX_CRT_NAME "None" +#endif // BX_CRT_ + #if BX_ARCH_32BIT # define BX_ARCH_NAME "32-bit" #elif BX_ARCH_64BIT diff --git a/3rdparty/bx/include/bx/process.h b/3rdparty/bx/include/bx/process.h deleted file mode 100644 index 03c8f120624..00000000000 --- a/3rdparty/bx/include/bx/process.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2017 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause - */ - -#ifndef BX_PROCESS_H_HEADER_GUARD -#define BX_PROCESS_H_HEADER_GUARD - -#include "string.h" -#include "uint32_t.h" - -#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD -# include <unistd.h> -#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD - -namespace bx -{ - /// - inline void* exec(const char* const* _argv) - { -#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD - pid_t pid = fork(); - - if (0 == pid) - { - int result = execvp(_argv[0], const_cast<char *const*>(&_argv[1]) ); - BX_UNUSED(result); - return NULL; - } - - return (void*)uintptr_t(pid); -#elif BX_PLATFORM_WINDOWS - STARTUPINFO si; - memset(&si, 0, sizeof(STARTUPINFO) ); - si.cb = sizeof(STARTUPINFO); - - PROCESS_INFORMATION pi; - memset(&pi, 0, sizeof(PROCESS_INFORMATION) ); - - int32_t total = 0; - for (uint32_t ii = 0; NULL != _argv[ii]; ++ii) - { - total += (int32_t)strlen(_argv[ii]) + 1; - } - - char* temp = (char*)alloca(total); - int32_t len = 0; - for(uint32_t ii = 0; NULL != _argv[ii]; ++ii) - { - len += snprintf(&temp[len], bx::uint32_imax(0, total-len) - , "%s " - , _argv[ii] - ); - } - - bool ok = CreateProcessA(_argv[0] - , temp - , NULL - , NULL - , false - , 0 - , NULL - , NULL - , &si - , &pi - ); - if (ok) - { - return pi.hProcess; - } - - return NULL; -#else - return NULL; -#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD - } - -} // namespace bx - -#endif // BX_PROCESS_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/radixsort.h b/3rdparty/bx/include/bx/radixsort.h index 2c4dd6a2408..87bd3e310b0 100644 --- a/3rdparty/bx/include/bx/radixsort.h +++ b/3rdparty/bx/include/bx/radixsort.h @@ -10,282 +10,42 @@ namespace bx { -#define BX_RADIXSORT_BITS 11 -#define BX_RADIXSORT_HISTOGRAM_SIZE (1<<BX_RADIXSORT_BITS) -#define BX_RADIXSORT_BIT_MASK (BX_RADIXSORT_HISTOGRAM_SIZE-1) - - inline void radixSort(uint32_t* __restrict _keys, uint32_t* __restrict _tempKeys, uint32_t _size) - { - uint32_t* __restrict keys = _keys; - uint32_t* __restrict tempKeys = _tempKeys; - - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; - uint16_t shift = 0; - uint32_t pass = 0; - for (; pass < 3; ++pass) - { - memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); - - bool sorted = true; - { - uint32_t key = keys[0]; - uint32_t prevKey = key; - for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) - { - key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - ++histogram[index]; - sorted &= prevKey <= key; - } - } - - if (sorted) - { - goto done; - } - - uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) - { - uint32_t count = histogram[ii]; - histogram[ii] = offset; - offset += count; - } - - for (uint32_t ii = 0; ii < _size; ++ii) - { - uint32_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - uint32_t dest = histogram[index]++; - tempKeys[dest] = key; - } - - uint32_t* swapKeys = tempKeys; - tempKeys = keys; - keys = swapKeys; - - shift += BX_RADIXSORT_BITS; - } - -done: - if (0 != (pass&1) ) - { - // Odd number of passes needs to do copy to the destination. - memcpy(_keys, _tempKeys, _size*sizeof(uint32_t) ); - } - } - + /// + void radixSort( + uint32_t* __restrict _keys + , uint32_t* __restrict _tempKeys + , uint32_t _size + ); + + /// template <typename Ty> - inline void radixSort(uint32_t* __restrict _keys, uint32_t* __restrict _tempKeys, Ty* __restrict _values, Ty* __restrict _tempValues, uint32_t _size) - { - uint32_t* __restrict keys = _keys; - uint32_t* __restrict tempKeys = _tempKeys; - Ty* __restrict values = _values; - Ty* __restrict tempValues = _tempValues; - - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; - uint16_t shift = 0; - uint32_t pass = 0; - for (; pass < 3; ++pass) - { - memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); - - bool sorted = true; - { - uint32_t key = keys[0]; - uint32_t prevKey = key; - for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) - { - key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - ++histogram[index]; - sorted &= prevKey <= key; - } - } - - if (sorted) - { - goto done; - } - - uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) - { - uint32_t count = histogram[ii]; - histogram[ii] = offset; - offset += count; - } - - for (uint32_t ii = 0; ii < _size; ++ii) - { - uint32_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - uint32_t dest = histogram[index]++; - tempKeys[dest] = key; - tempValues[dest] = values[ii]; - } - - uint32_t* swapKeys = tempKeys; - tempKeys = keys; - keys = swapKeys; - - Ty* swapValues = tempValues; - tempValues = values; - values = swapValues; - - shift += BX_RADIXSORT_BITS; - } - -done: - if (0 != (pass&1) ) - { - // Odd number of passes needs to do copy to the destination. - memcpy(_keys, _tempKeys, _size*sizeof(uint32_t) ); - for (uint32_t ii = 0; ii < _size; ++ii) - { - _values[ii] = _tempValues[ii]; - } - } - } - - inline void radixSort(uint64_t* __restrict _keys, uint64_t* __restrict _tempKeys, uint32_t _size) - { - uint64_t* __restrict keys = _keys; - uint64_t* __restrict tempKeys = _tempKeys; - - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; - uint16_t shift = 0; - uint32_t pass = 0; - for (; pass < 6; ++pass) - { - memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); - - bool sorted = true; - { - uint64_t key = keys[0]; - uint64_t prevKey = key; - for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) - { - key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - ++histogram[index]; - sorted &= prevKey <= key; - } - } - - if (sorted) - { - goto done; - } - - uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) - { - uint32_t count = histogram[ii]; - histogram[ii] = offset; - offset += count; - } - - for (uint32_t ii = 0; ii < _size; ++ii) - { - uint64_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - uint32_t dest = histogram[index]++; - tempKeys[dest] = key; - } - - uint64_t* swapKeys = tempKeys; - tempKeys = keys; - keys = swapKeys; - - shift += BX_RADIXSORT_BITS; - } - -done: - if (0 != (pass&1) ) - { - // Odd number of passes needs to do copy to the destination. - memcpy(_keys, _tempKeys, _size*sizeof(uint64_t) ); - } - } - + void radixSort( + uint32_t* __restrict _keys + , uint32_t* __restrict _tempKeys + , Ty* __restrict _values + , Ty* __restrict _tempValues + , uint32_t _size + ); + + /// + void radixSort( + uint64_t* __restrict _keys + , uint64_t* __restrict _tempKeys + , uint32_t _size + ); + + /// template <typename Ty> - inline void radixSort(uint64_t* __restrict _keys, uint64_t* __restrict _tempKeys, Ty* __restrict _values, Ty* __restrict _tempValues, uint32_t _size) - { - uint64_t* __restrict keys = _keys; - uint64_t* __restrict tempKeys = _tempKeys; - Ty* __restrict values = _values; - Ty* __restrict tempValues = _tempValues; - - uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; - uint16_t shift = 0; - uint32_t pass = 0; - for (; pass < 6; ++pass) - { - memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); - - bool sorted = true; - { - uint64_t key = keys[0]; - uint64_t prevKey = key; - for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) - { - key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - ++histogram[index]; - sorted &= prevKey <= key; - } - } - - if (sorted) - { - goto done; - } - - uint32_t offset = 0; - for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) - { - uint32_t count = histogram[ii]; - histogram[ii] = offset; - offset += count; - } - - for (uint32_t ii = 0; ii < _size; ++ii) - { - uint64_t key = keys[ii]; - uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; - uint32_t dest = histogram[index]++; - tempKeys[dest] = key; - tempValues[dest] = values[ii]; - } - - uint64_t* swapKeys = tempKeys; - tempKeys = keys; - keys = swapKeys; - - Ty* swapValues = tempValues; - tempValues = values; - values = swapValues; - - shift += BX_RADIXSORT_BITS; - } - -done: - if (0 != (pass&1) ) - { - // Odd number of passes needs to do copy to the destination. - memcpy(_keys, _tempKeys, _size*sizeof(uint64_t) ); - for (uint32_t ii = 0; ii < _size; ++ii) - { - _values[ii] = _tempValues[ii]; - } - } - } - -#undef BX_RADIXSORT_BITS -#undef BX_RADIXSORT_HISTOGRAM_SIZE -#undef BX_RADIXSORT_BIT_MASK + void radixSort( + uint64_t* __restrict _keys + , uint64_t* __restrict _tempKeys + , Ty* __restrict _values + , Ty* __restrict _tempValues + , uint32_t _size + ); } // namespace bx +#include "radixsort.inl" + #endif // BX_RADIXSORT_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/radixsort.inl b/3rdparty/bx/include/bx/radixsort.inl new file mode 100644 index 00000000000..2edc5e40fd3 --- /dev/null +++ b/3rdparty/bx/include/bx/radixsort.inl @@ -0,0 +1,288 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_RADIXSORT_H_HEADER_GUARD +# error "Must be included from bx/radixsort.h!" +#endif // BX_RADIXSORT_H_HEADER_GUARD + +namespace bx +{ +#define BX_RADIXSORT_BITS 11 +#define BX_RADIXSORT_HISTOGRAM_SIZE (1<<BX_RADIXSORT_BITS) +#define BX_RADIXSORT_BIT_MASK (BX_RADIXSORT_HISTOGRAM_SIZE-1) + + inline void radixSort(uint32_t* __restrict _keys, uint32_t* __restrict _tempKeys, uint32_t _size) + { + uint32_t* __restrict keys = _keys; + uint32_t* __restrict tempKeys = _tempKeys; + + uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint16_t shift = 0; + uint32_t pass = 0; + for (; pass < 3; ++pass) + { + memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + + bool sorted = true; + { + uint32_t key = keys[0]; + uint32_t prevKey = key; + for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) + { + key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + ++histogram[index]; + sorted &= prevKey <= key; + } + } + + if (sorted) + { + goto done; + } + + uint32_t offset = 0; + for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + { + uint32_t count = histogram[ii]; + histogram[ii] = offset; + offset += count; + } + + for (uint32_t ii = 0; ii < _size; ++ii) + { + uint32_t key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint32_t dest = histogram[index]++; + tempKeys[dest] = key; + } + + uint32_t* swapKeys = tempKeys; + tempKeys = keys; + keys = swapKeys; + + shift += BX_RADIXSORT_BITS; + } + +done: + if (0 != (pass&1) ) + { + // Odd number of passes needs to do copy to the destination. + memcpy(_keys, _tempKeys, _size*sizeof(uint32_t) ); + } + } + + template <typename Ty> + inline void radixSort(uint32_t* __restrict _keys, uint32_t* __restrict _tempKeys, Ty* __restrict _values, Ty* __restrict _tempValues, uint32_t _size) + { + uint32_t* __restrict keys = _keys; + uint32_t* __restrict tempKeys = _tempKeys; + Ty* __restrict values = _values; + Ty* __restrict tempValues = _tempValues; + + uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint16_t shift = 0; + uint32_t pass = 0; + for (; pass < 3; ++pass) + { + memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + + bool sorted = true; + { + uint32_t key = keys[0]; + uint32_t prevKey = key; + for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) + { + key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + ++histogram[index]; + sorted &= prevKey <= key; + } + } + + if (sorted) + { + goto done; + } + + uint32_t offset = 0; + for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + { + uint32_t count = histogram[ii]; + histogram[ii] = offset; + offset += count; + } + + for (uint32_t ii = 0; ii < _size; ++ii) + { + uint32_t key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint32_t dest = histogram[index]++; + tempKeys[dest] = key; + tempValues[dest] = values[ii]; + } + + uint32_t* swapKeys = tempKeys; + tempKeys = keys; + keys = swapKeys; + + Ty* swapValues = tempValues; + tempValues = values; + values = swapValues; + + shift += BX_RADIXSORT_BITS; + } + +done: + if (0 != (pass&1) ) + { + // Odd number of passes needs to do copy to the destination. + memcpy(_keys, _tempKeys, _size*sizeof(uint32_t) ); + for (uint32_t ii = 0; ii < _size; ++ii) + { + _values[ii] = _tempValues[ii]; + } + } + } + + inline void radixSort(uint64_t* __restrict _keys, uint64_t* __restrict _tempKeys, uint32_t _size) + { + uint64_t* __restrict keys = _keys; + uint64_t* __restrict tempKeys = _tempKeys; + + uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint16_t shift = 0; + uint32_t pass = 0; + for (; pass < 6; ++pass) + { + memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + + bool sorted = true; + { + uint64_t key = keys[0]; + uint64_t prevKey = key; + for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) + { + key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + ++histogram[index]; + sorted &= prevKey <= key; + } + } + + if (sorted) + { + goto done; + } + + uint32_t offset = 0; + for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + { + uint32_t count = histogram[ii]; + histogram[ii] = offset; + offset += count; + } + + for (uint32_t ii = 0; ii < _size; ++ii) + { + uint64_t key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint32_t dest = histogram[index]++; + tempKeys[dest] = key; + } + + uint64_t* swapKeys = tempKeys; + tempKeys = keys; + keys = swapKeys; + + shift += BX_RADIXSORT_BITS; + } + +done: + if (0 != (pass&1) ) + { + // Odd number of passes needs to do copy to the destination. + memcpy(_keys, _tempKeys, _size*sizeof(uint64_t) ); + } + } + + template <typename Ty> + inline void radixSort(uint64_t* __restrict _keys, uint64_t* __restrict _tempKeys, Ty* __restrict _values, Ty* __restrict _tempValues, uint32_t _size) + { + uint64_t* __restrict keys = _keys; + uint64_t* __restrict tempKeys = _tempKeys; + Ty* __restrict values = _values; + Ty* __restrict tempValues = _tempValues; + + uint32_t histogram[BX_RADIXSORT_HISTOGRAM_SIZE]; + uint16_t shift = 0; + uint32_t pass = 0; + for (; pass < 6; ++pass) + { + memset(histogram, 0, sizeof(uint32_t)*BX_RADIXSORT_HISTOGRAM_SIZE); + + bool sorted = true; + { + uint64_t key = keys[0]; + uint64_t prevKey = key; + for (uint32_t ii = 0; ii < _size; ++ii, prevKey = key) + { + key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + ++histogram[index]; + sorted &= prevKey <= key; + } + } + + if (sorted) + { + goto done; + } + + uint32_t offset = 0; + for (uint32_t ii = 0; ii < BX_RADIXSORT_HISTOGRAM_SIZE; ++ii) + { + uint32_t count = histogram[ii]; + histogram[ii] = offset; + offset += count; + } + + for (uint32_t ii = 0; ii < _size; ++ii) + { + uint64_t key = keys[ii]; + uint16_t index = (key>>shift)&BX_RADIXSORT_BIT_MASK; + uint32_t dest = histogram[index]++; + tempKeys[dest] = key; + tempValues[dest] = values[ii]; + } + + uint64_t* swapKeys = tempKeys; + tempKeys = keys; + keys = swapKeys; + + Ty* swapValues = tempValues; + tempValues = values; + values = swapValues; + + shift += BX_RADIXSORT_BITS; + } + +done: + if (0 != (pass&1) ) + { + // Odd number of passes needs to do copy to the destination. + memcpy(_keys, _tempKeys, _size*sizeof(uint64_t) ); + for (uint32_t ii = 0; ii < _size; ++ii) + { + _values[ii] = _tempValues[ii]; + } + } + } + +#undef BX_RADIXSORT_BITS +#undef BX_RADIXSORT_HISTOGRAM_SIZE +#undef BX_RADIXSORT_BIT_MASK + +} // namespace bx diff --git a/3rdparty/bx/include/bx/readerwriter.h b/3rdparty/bx/include/bx/readerwriter.h index d926628430d..19411a6adb7 100644 --- a/3rdparty/bx/include/bx/readerwriter.h +++ b/3rdparty/bx/include/bx/readerwriter.h @@ -24,6 +24,7 @@ BX_ERROR_RESULT(BX_ERROR_READERWRITER_ALREADY_OPEN, BX_MAKEFOURCC('R', 'W', 0, 5 namespace bx { + /// struct Whence { enum Enum @@ -34,350 +35,111 @@ namespace bx }; }; + /// struct BX_NO_VTABLE ReaderI { virtual ~ReaderI() = 0; virtual int32_t read(void* _data, int32_t _size, Error* _err) = 0; }; - inline ReaderI::~ReaderI() - { - } - + /// struct BX_NO_VTABLE WriterI { virtual ~WriterI() = 0; virtual int32_t write(const void* _data, int32_t _size, Error* _err) = 0; }; - inline WriterI::~WriterI() - { - } - + /// struct BX_NO_VTABLE SeekerI { virtual ~SeekerI() = 0; virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) = 0; }; - inline SeekerI::~SeekerI() - { - } - - /// Read data. - inline int32_t read(ReaderI* _reader, void* _data, int32_t _size, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - return _reader->read(_data, _size, _err); - } - - /// Read value. - template<typename Ty> - inline int32_t read(ReaderI* _reader, Ty& _value, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - return _reader->read(&_value, sizeof(Ty), _err); - } - - /// Read value and converts it to host endianess. _fromLittleEndian specifies - /// underlying stream endianess. - template<typename Ty> - inline int32_t readHE(ReaderI* _reader, Ty& _value, bool _fromLittleEndian, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - Ty value; - int32_t result = _reader->read(&value, sizeof(Ty), _err); - _value = toHostEndian(value, _fromLittleEndian); - return result; - } - - /// Write data. - inline int32_t write(WriterI* _writer, const void* _data, int32_t _size, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - return _writer->write(_data, _size, _err); - } - - /// Write repeat the same value. - inline int32_t writeRep(WriterI* _writer, uint8_t _byte, int32_t _size, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - - const uint32_t tmp0 = uint32_sels(64 - _size, 64, _size); - const uint32_t tmp1 = uint32_sels(256 - _size, 256, tmp0); - const uint32_t blockSize = uint32_sels(1024 - _size, 1024, tmp1); - uint8_t* temp = (uint8_t*)alloca(blockSize); - memset(temp, _byte, blockSize); - - int32_t size = 0; - while (0 < _size) - { - int32_t bytes = write(_writer, temp, uint32_min(blockSize, _size), _err); - size += bytes; - _size -= bytes; - } - - return size; - } - - /// Write value. - template<typename Ty> - inline int32_t write(WriterI* _writer, const Ty& _value, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - return _writer->write(&_value, sizeof(Ty), _err); - } - - /// Write value as little endian. - template<typename Ty> - inline int32_t writeLE(WriterI* _writer, const Ty& _value, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - Ty value = toLittleEndian(_value); - int32_t result = _writer->write(&value, sizeof(Ty), _err); - return result; - } - - /// Write value as big endian. - template<typename Ty> - inline int32_t writeBE(WriterI* _writer, const Ty& _value, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - Ty value = toBigEndian(_value); - int32_t result = _writer->write(&value, sizeof(Ty), _err); - return result; - } - - /// Write formated string. - inline int32_t writePrintf(WriterI* _writer, const char* _format, ...) - { - va_list argList; - va_start(argList, _format); - - char temp[2048]; - char* out = temp; - int32_t max = sizeof(temp); - int32_t len = vsnprintf(out, max, _format, argList); - if (len > max) - { - out = (char*)alloca(len); - len = vsnprintf(out, len, _format, argList); - } - - int32_t size = write(_writer, out, len); - - va_end(argList); - - return size; - } - - /// Skip _offset bytes forward. - inline int64_t skip(SeekerI* _seeker, int64_t _offset) - { - return _seeker->seek(_offset, Whence::Current); - } - - /// Seek to any position in file. - inline int64_t seek(SeekerI* _seeker, int64_t _offset = 0, Whence::Enum _whence = Whence::Current) - { - return _seeker->seek(_offset, _whence); - } - - /// Returns size of file. - inline int64_t getSize(SeekerI* _seeker) - { - int64_t offset = _seeker->seek(); - int64_t size = _seeker->seek(0, Whence::End); - _seeker->seek(offset, Whence::Begin); - return size; - } - + /// struct BX_NO_VTABLE ReaderSeekerI : public ReaderI, public SeekerI { }; - /// Peek data. - inline int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - int64_t offset = bx::seek(_reader); - int32_t size = _reader->read(_data, _size, _err); - bx::seek(_reader, offset, bx::Whence::Begin); - return size; - } - - /// Peek value. - template<typename Ty> - inline int32_t peek(ReaderSeekerI* _reader, Ty& _value, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); - return peek(_reader, &_value, sizeof(Ty), _err); - } - + /// struct BX_NO_VTABLE WriterSeekerI : public WriterI, public SeekerI { }; - /// Align reader stream. - inline int32_t align(ReaderSeekerI* _reader, uint32_t _alignment, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - const int64_t current = bx::seek(_reader); - const int64_t aligned = ( (current + _alignment-1)/_alignment) * _alignment; - const int32_t size = int32_t(aligned - current); - if (0 != size) - { - const int64_t offset = bx::seek(_reader, size); - if (offset != aligned) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "Align: read truncated."); - } - return int32_t(offset - current); - } - - return 0; - } - - /// Align writer stream (pads stream with zeros). - inline int32_t align(WriterSeekerI* _writer, uint32_t _alignment, Error* _err = NULL) - { - BX_ERROR_SCOPE(_err); - const int64_t current = bx::seek(_writer); - const int64_t aligned = ( (current + _alignment-1)/_alignment) * _alignment; - const int32_t size = int32_t(aligned - current); - if (0 != size) - { - return writeRep(_writer, 0, size, _err); - } - - return 0; - } - + /// struct BX_NO_VTABLE ReaderOpenI { virtual ~ReaderOpenI() = 0; virtual bool open(const char* _filePath, Error* _err) = 0; }; - inline ReaderOpenI::~ReaderOpenI() - { - } - + /// struct BX_NO_VTABLE WriterOpenI { virtual ~WriterOpenI() = 0; virtual bool open(const char* _filePath, bool _append, Error* _err) = 0; }; - inline WriterOpenI::~WriterOpenI() - { - } - + /// struct BX_NO_VTABLE CloserI { virtual ~CloserI() = 0; virtual void close() = 0; }; - inline CloserI::~CloserI() - { - } - + /// struct BX_NO_VTABLE FileReaderI : public ReaderOpenI, public CloserI, public ReaderSeekerI { }; + /// struct BX_NO_VTABLE FileWriterI : public WriterOpenI, public CloserI, public WriterSeekerI { }; - inline bool open(ReaderOpenI* _reader, const char* _filePath, Error* _err = NULL) - { - BX_ERROR_USE_TEMP_WHEN_NULL(_err); - return _reader->open(_filePath, _err); - } - - inline bool open(WriterOpenI* _writer, const char* _filePath, bool _append = false, Error* _err = NULL) - { - BX_ERROR_USE_TEMP_WHEN_NULL(_err); - return _writer->open(_filePath, _append, _err); - } - - inline void close(CloserI* _reader) - { - _reader->close(); - } - + /// struct BX_NO_VTABLE MemoryBlockI { virtual void* more(uint32_t _size = 0) = 0; virtual uint32_t getSize() = 0; }; + /// class StaticMemoryBlock : public MemoryBlockI { public: - StaticMemoryBlock(void* _data, uint32_t _size) - : m_data(_data) - , m_size(_size) - { - } + /// + StaticMemoryBlock(void* _data, uint32_t _size); - virtual ~StaticMemoryBlock() - { - } + /// + virtual ~StaticMemoryBlock(); - virtual void* more(uint32_t /*_size*/ = 0) BX_OVERRIDE - { - return m_data; - } + /// + virtual void* more(uint32_t _size = 0); - virtual uint32_t getSize() BX_OVERRIDE - { - return m_size; - } + /// + virtual uint32_t getSize() BX_OVERRIDE; private: void* m_data; uint32_t m_size; }; + /// class MemoryBlock : public MemoryBlockI { public: - MemoryBlock(AllocatorI* _allocator) - : m_allocator(_allocator) - , m_data(NULL) - , m_size(0) - { - } + /// + MemoryBlock(AllocatorI* _allocator); - virtual ~MemoryBlock() - { - BX_FREE(m_allocator, m_data); - } + /// + virtual ~MemoryBlock(); - virtual void* more(uint32_t _size = 0) BX_OVERRIDE - { - if (0 < _size) - { - m_size += _size; - m_data = BX_REALLOC(m_allocator, m_data, m_size); - } + /// + virtual void* more(uint32_t _size = 0) BX_OVERRIDE; - return m_data; - } - - virtual uint32_t getSize() BX_OVERRIDE - { - return m_size; - } + /// + virtual uint32_t getSize() BX_OVERRIDE; private: AllocatorI* m_allocator; @@ -385,128 +147,51 @@ namespace bx uint32_t m_size; }; + /// class SizerWriter : public WriterSeekerI { public: - SizerWriter() - : m_pos(0) - , m_top(0) - { - } - - virtual ~SizerWriter() - { - } - - virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE - { - switch (_whence) - { - case Whence::Begin: - m_pos = int64_clamp(_offset, 0, m_top); - break; - - case Whence::Current: - m_pos = int64_clamp(m_pos + _offset, 0, m_top); - break; - - case Whence::End: - m_pos = int64_clamp(m_top - _offset, 0, m_top); - break; - } - - return m_pos; - } - - virtual int32_t write(const void* /*_data*/, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + /// + SizerWriter(); - int32_t morecore = int32_t(m_pos - m_top) + _size; + /// + virtual ~SizerWriter(); - if (0 < morecore) - { - m_top += morecore; - } + /// + virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE; - int64_t remainder = m_top-m_pos; - int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); - m_pos += size; - if (size != _size) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "SizerWriter: write truncated."); - } - return size; - } + /// + virtual int32_t write(const void* /*_data*/, int32_t _size, Error* _err) BX_OVERRIDE; private: int64_t m_pos; int64_t m_top; }; + /// class MemoryReader : public ReaderSeekerI { public: - MemoryReader(const void* _data, uint32_t _size) - : m_data( (const uint8_t*)_data) - , m_pos(0) - , m_top(_size) - { - } - - virtual ~MemoryReader() - { - } - - virtual int64_t seek(int64_t _offset, Whence::Enum _whence) BX_OVERRIDE - { - switch (_whence) - { - case Whence::Begin: - m_pos = int64_clamp(_offset, 0, m_top); - break; + /// + MemoryReader(const void* _data, uint32_t _size); - case Whence::Current: - m_pos = int64_clamp(m_pos + _offset, 0, m_top); - break; + /// + virtual ~MemoryReader(); - case Whence::End: - m_pos = int64_clamp(m_top - _offset, 0, m_top); - break; - } + /// + virtual int64_t seek(int64_t _offset, Whence::Enum _whence) BX_OVERRIDE; - return m_pos; - } + /// + virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE; - virtual int32_t read(void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - int64_t remainder = m_top-m_pos; - int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); - memcpy(_data, &m_data[m_pos], size); - m_pos += size; - if (size != _size) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "MemoryReader: read truncated."); - } - return size; - } - - const uint8_t* getDataPtr() const - { - return &m_data[m_pos]; - } + /// + const uint8_t* getDataPtr() const; - int64_t getPos() const - { - return m_pos; - } + /// + int64_t getPos() const; - int64_t remaining() const - { - return m_top-m_pos; - } + /// + int64_t remaining() const; private: const uint8_t* m_data; @@ -514,66 +199,21 @@ namespace bx int64_t m_top; }; + /// class MemoryWriter : public WriterSeekerI { public: - MemoryWriter(MemoryBlockI* _memBlock) - : m_memBlock(_memBlock) - , m_data(NULL) - , m_pos(0) - , m_top(0) - , m_size(0) - { - } + /// + MemoryWriter(MemoryBlockI* _memBlock); - virtual ~MemoryWriter() - { - } - - virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE - { - switch (_whence) - { - case Whence::Begin: - m_pos = int64_clamp(_offset, 0, m_top); - break; - - case Whence::Current: - m_pos = int64_clamp(m_pos + _offset, 0, m_top); - break; - - case Whence::End: - m_pos = int64_clamp(m_top - _offset, 0, m_top); - break; - } + /// + virtual ~MemoryWriter(); - return m_pos; - } + /// + virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) BX_OVERRIDE; - virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE - { - BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); - - int32_t morecore = int32_t(m_pos - m_size) + _size; - - if (0 < morecore) - { - morecore = BX_ALIGN_MASK(morecore, 0xfff); - m_data = (uint8_t*)m_memBlock->more(morecore); - m_size = m_memBlock->getSize(); - } - - int64_t remainder = m_size-m_pos; - int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); - memcpy(&m_data[m_pos], _data, size); - m_pos += size; - m_top = int64_max(m_top, m_pos); - if (size != _size) - { - BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "MemoryWriter: write truncated."); - } - return size; - } + /// + virtual int32_t write(const void* _data, int32_t _size, Error* _err) BX_OVERRIDE; private: MemoryBlockI* m_memBlock; @@ -583,23 +223,86 @@ namespace bx int64_t m_size; }; + /// class StaticMemoryBlockWriter : public MemoryWriter { public: - StaticMemoryBlockWriter(void* _data, uint32_t _size) - : MemoryWriter(&m_smb) - , m_smb(_data, _size) - { - } + /// + StaticMemoryBlockWriter(void* _data, uint32_t _size); - ~StaticMemoryBlockWriter() - { - } + /// + virtual ~StaticMemoryBlockWriter(); private: StaticMemoryBlock m_smb; }; + /// Read data. + int32_t read(ReaderI* _reader, void* _data, int32_t _size, Error* _err = NULL); + + /// Read value. + template<typename Ty> + int32_t read(ReaderI* _reader, Ty& _value, Error* _err = NULL); + + /// Read value and converts it to host endianess. _fromLittleEndian specifies + /// underlying stream endianess. + template<typename Ty> + int32_t readHE(ReaderI* _reader, Ty& _value, bool _fromLittleEndian, Error* _err = NULL); + + /// Write data. + int32_t write(WriterI* _writer, const void* _data, int32_t _size, Error* _err = NULL); + + /// Write repeat the same value. + int32_t writeRep(WriterI* _writer, uint8_t _byte, int32_t _size, Error* _err = NULL); + + /// Write value. + template<typename Ty> + int32_t write(WriterI* _writer, const Ty& _value, Error* _err = NULL); + + /// Write value as little endian. + template<typename Ty> + int32_t writeLE(WriterI* _writer, const Ty& _value, Error* _err = NULL); + + /// Write value as big endian. + template<typename Ty> + int32_t writeBE(WriterI* _writer, const Ty& _value, Error* _err = NULL); + + /// Write formated string. + int32_t writePrintf(WriterI* _writer, const char* _format, ...); + + /// Skip _offset bytes forward. + int64_t skip(SeekerI* _seeker, int64_t _offset); + + /// Seek to any position in file. + int64_t seek(SeekerI* _seeker, int64_t _offset = 0, Whence::Enum _whence = Whence::Current); + + /// Returns size of file. + int64_t getSize(SeekerI* _seeker); + + /// Peek data. + int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err = NULL); + + /// Peek value. + template<typename Ty> + int32_t peek(ReaderSeekerI* _reader, Ty& _value, Error* _err = NULL); + + /// Align reader stream. + int32_t align(ReaderSeekerI* _reader, uint32_t _alignment, Error* _err = NULL); + + /// Align writer stream (pads stream with zeros). + int32_t align(WriterSeekerI* _writer, uint32_t _alignment, Error* _err = NULL); + + /// + bool open(ReaderOpenI* _reader, const char* _filePath, Error* _err = NULL); + + /// + bool open(WriterOpenI* _writer, const char* _filePath, bool _append = false, Error* _err = NULL); + + /// + void close(CloserI* _reader); + } // namespace bx +#include "readerwriter.inl" + #endif // BX_READERWRITER_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/readerwriter.inl b/3rdparty/bx/include/bx/readerwriter.inl new file mode 100644 index 00000000000..9ba8517776c --- /dev/null +++ b/3rdparty/bx/include/bx/readerwriter.inl @@ -0,0 +1,452 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_READERWRITER_H_HEADER_GUARD +# error "Must be included from bx/readerwriter!" +#endif // BX_READERWRITER_H_HEADER_GUARD + +namespace bx +{ + inline ReaderI::~ReaderI() + { + } + + inline WriterI::~WriterI() + { + } + + inline SeekerI::~SeekerI() + { + } + + inline ReaderOpenI::~ReaderOpenI() + { + } + + inline WriterOpenI::~WriterOpenI() + { + } + + inline CloserI::~CloserI() + { + } + + inline StaticMemoryBlock::StaticMemoryBlock(void* _data, uint32_t _size) + : m_data(_data) + , m_size(_size) + { + } + + inline StaticMemoryBlock::~StaticMemoryBlock() + { + } + + inline void* StaticMemoryBlock::more(uint32_t _size) + { + BX_UNUSED(_size); + return m_data; + } + + inline uint32_t StaticMemoryBlock::getSize() + { + return m_size; + } + + inline MemoryBlock::MemoryBlock(AllocatorI* _allocator) + : m_allocator(_allocator) + , m_data(NULL) + , m_size(0) + { + } + + inline MemoryBlock::~MemoryBlock() + { + BX_FREE(m_allocator, m_data); + } + + inline void* MemoryBlock::more(uint32_t _size) + { + if (0 < _size) + { + m_size += _size; + m_data = BX_REALLOC(m_allocator, m_data, m_size); + } + + return m_data; + } + + inline uint32_t MemoryBlock::getSize() + { + return m_size; + } + + inline SizerWriter::SizerWriter() + : m_pos(0) + , m_top(0) + { + } + + inline SizerWriter::~SizerWriter() + { + } + + inline int64_t SizerWriter::seek(int64_t _offset, Whence::Enum _whence) + { + switch (_whence) + { + case Whence::Begin: + m_pos = int64_clamp(_offset, 0, m_top); + break; + + case Whence::Current: + m_pos = int64_clamp(m_pos + _offset, 0, m_top); + break; + + case Whence::End: + m_pos = int64_clamp(m_top - _offset, 0, m_top); + break; + } + + return m_pos; + } + + inline int32_t SizerWriter::write(const void* /*_data*/, int32_t _size, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + int32_t morecore = int32_t(m_pos - m_top) + _size; + + if (0 < morecore) + { + m_top += morecore; + } + + int64_t remainder = m_top-m_pos; + int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); + m_pos += size; + if (size != _size) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "SizerWriter: write truncated."); + } + return size; + } + + inline MemoryReader::MemoryReader(const void* _data, uint32_t _size) + : m_data( (const uint8_t*)_data) + , m_pos(0) + , m_top(_size) + { + } + + inline MemoryReader::~MemoryReader() + { + } + + inline int64_t MemoryReader::seek(int64_t _offset, Whence::Enum _whence) + { + switch (_whence) + { + case Whence::Begin: + m_pos = int64_clamp(_offset, 0, m_top); + break; + + case Whence::Current: + m_pos = int64_clamp(m_pos + _offset, 0, m_top); + break; + + case Whence::End: + m_pos = int64_clamp(m_top - _offset, 0, m_top); + break; + } + + return m_pos; + } + + inline int32_t MemoryReader::read(void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + int64_t remainder = m_top-m_pos; + int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); + memcpy(_data, &m_data[m_pos], size); + m_pos += size; + if (size != _size) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "MemoryReader: read truncated."); + } + return size; + } + + inline const uint8_t* MemoryReader::getDataPtr() const + { + return &m_data[m_pos]; + } + + inline int64_t MemoryReader::getPos() const + { + return m_pos; + } + + inline int64_t MemoryReader::remaining() const + { + return m_top-m_pos; + } + + inline MemoryWriter::MemoryWriter(MemoryBlockI* _memBlock) + : m_memBlock(_memBlock) + , m_data(NULL) + , m_pos(0) + , m_top(0) + , m_size(0) + { + } + + inline MemoryWriter::~MemoryWriter() + { + } + + inline int64_t MemoryWriter::seek(int64_t _offset, Whence::Enum _whence) + { + switch (_whence) + { + case Whence::Begin: + m_pos = int64_clamp(_offset, 0, m_top); + break; + + case Whence::Current: + m_pos = int64_clamp(m_pos + _offset, 0, m_top); + break; + + case Whence::End: + m_pos = int64_clamp(m_top - _offset, 0, m_top); + break; + } + + return m_pos; + } + + inline int32_t MemoryWriter::write(const void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + int32_t morecore = int32_t(m_pos - m_size) + _size; + + if (0 < morecore) + { + morecore = BX_ALIGN_MASK(morecore, 0xfff); + m_data = (uint8_t*)m_memBlock->more(morecore); + m_size = m_memBlock->getSize(); + } + + int64_t remainder = m_size-m_pos; + int32_t size = uint32_min(_size, uint32_t(int64_min(remainder, INT32_MAX) ) ); + memcpy(&m_data[m_pos], _data, size); + m_pos += size; + m_top = int64_max(m_top, m_pos); + if (size != _size) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "MemoryWriter: write truncated."); + } + return size; + } + + inline StaticMemoryBlockWriter::StaticMemoryBlockWriter(void* _data, uint32_t _size) + : MemoryWriter(&m_smb) + , m_smb(_data, _size) + { + } + + inline StaticMemoryBlockWriter::~StaticMemoryBlockWriter() + { + } + + inline int32_t read(ReaderI* _reader, void* _data, int32_t _size, Error* _err) + { + BX_ERROR_SCOPE(_err); + return _reader->read(_data, _size, _err); + } + + template<typename Ty> + int32_t read(ReaderI* _reader, Ty& _value, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + return _reader->read(&_value, sizeof(Ty), _err); + } + + template<typename Ty> + int32_t readHE(ReaderI* _reader, Ty& _value, bool _fromLittleEndian, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + Ty value; + int32_t result = _reader->read(&value, sizeof(Ty), _err); + _value = toHostEndian(value, _fromLittleEndian); + return result; + } + + inline int32_t write(WriterI* _writer, const void* _data, int32_t _size, Error* _err) + { + BX_ERROR_SCOPE(_err); + return _writer->write(_data, _size, _err); + } + + inline int32_t writeRep(WriterI* _writer, uint8_t _byte, int32_t _size, Error* _err) + { + BX_ERROR_SCOPE(_err); + + const uint32_t tmp0 = uint32_sels(64 - _size, 64, _size); + const uint32_t tmp1 = uint32_sels(256 - _size, 256, tmp0); + const uint32_t blockSize = uint32_sels(1024 - _size, 1024, tmp1); + uint8_t* temp = (uint8_t*)alloca(blockSize); + memset(temp, _byte, blockSize); + + int32_t size = 0; + while (0 < _size) + { + int32_t bytes = write(_writer, temp, uint32_min(blockSize, _size), _err); + size += bytes; + _size -= bytes; + } + + return size; + } + + template<typename Ty> + int32_t write(WriterI* _writer, const Ty& _value, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + return _writer->write(&_value, sizeof(Ty), _err); + } + + template<typename Ty> + int32_t writeLE(WriterI* _writer, const Ty& _value, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + Ty value = toLittleEndian(_value); + int32_t result = _writer->write(&value, sizeof(Ty), _err); + return result; + } + + template<typename Ty> + int32_t writeBE(WriterI* _writer, const Ty& _value, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + Ty value = toBigEndian(_value); + int32_t result = _writer->write(&value, sizeof(Ty), _err); + return result; + } + + inline int32_t writePrintf(WriterI* _writer, const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + + char temp[2048]; + char* out = temp; + int32_t max = sizeof(temp); + int32_t len = vsnprintf(out, max, _format, argList); + if (len > max) + { + out = (char*)alloca(len); + len = vsnprintf(out, len, _format, argList); + } + + int32_t size = write(_writer, out, len); + + va_end(argList); + + return size; + } + + inline int64_t skip(SeekerI* _seeker, int64_t _offset) + { + return _seeker->seek(_offset, Whence::Current); + } + + inline int64_t seek(SeekerI* _seeker, int64_t _offset, Whence::Enum _whence) + { + return _seeker->seek(_offset, _whence); + } + + inline int64_t getSize(SeekerI* _seeker) + { + int64_t offset = _seeker->seek(); + int64_t size = _seeker->seek(0, Whence::End); + _seeker->seek(offset, Whence::Begin); + return size; + } + + inline int32_t peek(ReaderSeekerI* _reader, void* _data, int32_t _size, Error* _err) + { + BX_ERROR_SCOPE(_err); + int64_t offset = bx::seek(_reader); + int32_t size = _reader->read(_data, _size, _err); + bx::seek(_reader, offset, bx::Whence::Begin); + return size; + } + + template<typename Ty> + int32_t peek(ReaderSeekerI* _reader, Ty& _value, Error* _err) + { + BX_ERROR_SCOPE(_err); + BX_STATIC_ASSERT(BX_TYPE_IS_POD(Ty) ); + return peek(_reader, &_value, sizeof(Ty), _err); + } + + inline int32_t align(ReaderSeekerI* _reader, uint32_t _alignment, Error* _err) + { + BX_ERROR_SCOPE(_err); + const int64_t current = bx::seek(_reader); + const int64_t aligned = ( (current + _alignment-1)/_alignment) * _alignment; + const int32_t size = int32_t(aligned - current); + if (0 != size) + { + const int64_t offset = bx::seek(_reader, size); + if (offset != aligned) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "Align: read truncated."); + } + return int32_t(offset - current); + } + + return 0; + } + + inline int32_t align(WriterSeekerI* _writer, uint32_t _alignment, Error* _err) + { + BX_ERROR_SCOPE(_err); + const int64_t current = bx::seek(_writer); + const int64_t aligned = ( (current + _alignment-1)/_alignment) * _alignment; + const int32_t size = int32_t(aligned - current); + if (0 != size) + { + return writeRep(_writer, 0, size, _err); + } + + return 0; + } + + inline bool open(ReaderOpenI* _reader, const char* _filePath, Error* _err) + { + BX_ERROR_USE_TEMP_WHEN_NULL(_err); + return _reader->open(_filePath, _err); + } + + inline bool open(WriterOpenI* _writer, const char* _filePath, bool _append, Error* _err) + { + BX_ERROR_USE_TEMP_WHEN_NULL(_err); + return _writer->open(_filePath, _append, _err); + } + + inline void close(CloserI* _reader) + { + _reader->close(); + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/rng.h b/3rdparty/bx/include/bx/rng.h index cff323c2f95..91eade62644 100644 --- a/3rdparty/bx/include/bx/rng.h +++ b/3rdparty/bx/include/bx/rng.h @@ -12,83 +12,54 @@ namespace bx { - // George Marsaglia's MWC + /// George Marsaglia's MWC class RngMwc { public: - RngMwc(uint32_t _z = 12345, uint32_t _w = 65435) - : m_z(_z) - , m_w(_w) - { - } - - void reset(uint32_t _z = 12345, uint32_t _w = 65435) - { - m_z = _z; - m_w = _w; - } - - uint32_t gen() - { - m_z = 36969*(m_z&65535)+(m_z>>16); - m_w = 18000*(m_w&65535)+(m_w>>16); - return (m_z<<16)+m_w; - } + /// + RngMwc(uint32_t _z = 12345, uint32_t _w = 65435); + + /// + void reset(uint32_t _z = 12345, uint32_t _w = 65435); + + /// + uint32_t gen(); private: uint32_t m_z; uint32_t m_w; }; - // George Marsaglia's FIB + /// George Marsaglia's FIB class RngFib { public: - RngFib() - : m_a(9983651) - , m_b(95746118) - { - } - - void reset() - { - m_a = 9983651; - m_b = 95746118; - } - - uint32_t gen() - { - m_b = m_a+m_b; - m_a = m_b-m_a; - return m_a; - } + /// + RngFib(uint32_t _a = 9983651, uint32_t _b = 95746118); + + /// + void reset(uint32_t _a = 9983651, uint32_t _b = 95746118); + + /// + uint32_t gen(); private: uint32_t m_a; uint32_t m_b; }; - // George Marsaglia's SHR3 + /// George Marsaglia's SHR3 class RngShr3 { public: - RngShr3(uint32_t _jsr = 34221) - : m_jsr(_jsr) - { - } - - void reset(uint32_t _jsr = 34221) - { - m_jsr = _jsr; - } - - uint32_t gen() - { - m_jsr ^= m_jsr<<17; - m_jsr ^= m_jsr>>13; - m_jsr ^= m_jsr<<5; - return m_jsr; - } + /// + RngShr3(uint32_t _jsr = 34221); + + /// + void reset(uint32_t _jsr = 34221); + + /// + uint32_t gen(); private: uint32_t m_jsr; @@ -96,112 +67,35 @@ namespace bx /// Returns random number between 0.0f and 1.0f. template <typename Rng> - inline float frnd(Rng* _rng) - { - uint32_t rnd = _rng->gen() & UINT16_MAX; - return float(rnd) * 1.0f/float(UINT16_MAX); - } + float frnd(Rng* _rng); /// Returns random number between -1.0f and 1.0f. template <typename Rng> - inline float frndh(Rng* _rng) - { - return 2.0f * bx::frnd(_rng) - 1.0f; - } + float frndh(Rng* _rng); /// Generate random point on unit circle. template <typename Rng> - inline void randUnitCircle(float _result[3], Rng* _rng) - { - const float angle = frnd(_rng) * pi * 2.0f; - - _result[0] = fcos(angle); - _result[1] = 0.0f; - _result[2] = fsin(angle); - } + void randUnitCircle(float _result[3], Rng* _rng); /// Generate random point on unit sphere. template <typename Rng> - inline void randUnitSphere(float _result[3], Rng* _rng) - { - const float rand0 = frnd(_rng) * 2.0f - 1.0f; - const float rand1 = frnd(_rng) * pi * 2.0f; - const float sqrtf1 = fsqrt(1.0f - rand0*rand0); - - _result[0] = sqrtf1 * fcos(rand1); - _result[1] = sqrtf1 * fsin(rand1); - _result[2] = rand0; - } + void randUnitSphere(float _result[3], Rng* _rng); /// Generate random point on unit hemisphere. template <typename Ty> - inline void randUnitHemisphere(float _result[3], Ty* _rng, const float _normal[3]) - { - float dir[3]; - randUnitSphere(dir, _rng); - - float DdotN = dir[0]*_normal[0] - + dir[1]*_normal[1] - + dir[2]*_normal[2] - ; - - if (0.0f > DdotN) - { - dir[0] = -dir[0]; - dir[1] = -dir[1]; - dir[2] = -dir[2]; - } - - _result[0] = dir[0]; - _result[1] = dir[1]; - _result[2] = dir[2]; - } + void randUnitHemisphere(float _result[3], Ty* _rng, const float _normal[3]); /// Sampling with Hammersley and Halton Points /// http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html /// - inline void generateSphereHammersley(void* _data, uint32_t _stride, uint32_t _num, float _scale = 1.0f) - { - uint8_t* data = (uint8_t*)_data; - - for (uint32_t ii = 0; ii < _num; ii++) - { - float tt = 0.0f; - float pp = 0.5; - for (uint32_t jj = ii; jj; jj >>= 1) - { - tt += (jj & 1) ? pp : 0.0f; - pp *= 0.5f; - } - - tt = 2.0f * tt - 1.0f; - - const float phi = (ii + 0.5f) / _num; - const float phirad = phi * 2.0f * pi; - const float st = fsqrt(1.0f-tt*tt) * _scale; - - float* xyz = (float*)data; - data += _stride; - - xyz[0] = st * fcos(phirad); - xyz[1] = st * fsin(phirad); - xyz[2] = tt * _scale; - } - } + void generateSphereHammersley(void* _data, uint32_t _stride, uint32_t _num, float _scale = 1.0f); /// Fisher-Yates shuffle. template<typename Rng, typename Ty> - inline void shuffle(Rng* _rng, Ty* _array, uint32_t _num) - { - BX_CHECK(_num != 0, "Number of elements can't be 0!"); - - for (uint32_t ii = 0, num = _num-1; ii < num; ++ii) - { - uint32_t jj = ii + 1 + _rng->gen() % (num - ii); - bx::xchg(_array[ii], _array[jj]); - } - } + void shuffle(Rng* _rng, Ty* _array, uint32_t _num); } // namespace bx +#include "rng.inl" + #endif // BX_RNG_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/rng.inl b/3rdparty/bx/include/bx/rng.inl new file mode 100644 index 00000000000..02a4d21e5bc --- /dev/null +++ b/3rdparty/bx/include/bx/rng.inl @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_RNG_H_HEADER_GUARD +# error "Must be included from bx/rng.h!" +#endif // BX_RNG_H_HEADER_GUARD + +#include "bx.h" +#include "fpumath.h" +#include "uint32_t.h" + +namespace bx +{ + inline RngMwc::RngMwc(uint32_t _z, uint32_t _w) + : m_z(_z) + , m_w(_w) + { + } + + inline void RngMwc::reset(uint32_t _z, uint32_t _w) + { + m_z = _z; + m_w = _w; + } + + inline uint32_t RngMwc::gen() + { + m_z = 36969*(m_z&65535)+(m_z>>16); + m_w = 18000*(m_w&65535)+(m_w>>16); + return (m_z<<16)+m_w; + } + + inline RngFib::RngFib(uint32_t _a, uint32_t _b) + : m_a(_a) + , m_b(_b) + { + } + + inline void RngFib::reset(uint32_t _a, uint32_t _b) + { + m_a = _a; + m_b = _b; + } + + inline uint32_t RngFib::gen() + { + m_b = m_a+m_b; + m_a = m_b-m_a; + return m_a; + } + + inline RngShr3::RngShr3(uint32_t _jsr) + : m_jsr(_jsr) + { + } + + inline void RngShr3::reset(uint32_t _jsr) + { + m_jsr = _jsr; + } + + inline uint32_t RngShr3::gen() + { + m_jsr ^= m_jsr<<17; + m_jsr ^= m_jsr>>13; + m_jsr ^= m_jsr<<5; + return m_jsr; + } + + template <typename Rng> + inline float frnd(Rng* _rng) + { + uint32_t rnd = _rng->gen() & UINT16_MAX; + return float(rnd) * 1.0f/float(UINT16_MAX); + } + + template <typename Rng> + inline float frndh(Rng* _rng) + { + return 2.0f * bx::frnd(_rng) - 1.0f; + } + + template <typename Rng> + inline void randUnitCircle(float _result[3], Rng* _rng) + { + const float angle = frnd(_rng) * pi * 2.0f; + + _result[0] = fcos(angle); + _result[1] = 0.0f; + _result[2] = fsin(angle); + } + + template <typename Rng> + inline void randUnitSphere(float _result[3], Rng* _rng) + { + const float rand0 = frnd(_rng) * 2.0f - 1.0f; + const float rand1 = frnd(_rng) * pi * 2.0f; + const float sqrtf1 = fsqrt(1.0f - rand0*rand0); + + _result[0] = sqrtf1 * fcos(rand1); + _result[1] = sqrtf1 * fsin(rand1); + _result[2] = rand0; + } + + template <typename Ty> + inline void randUnitHemisphere(float _result[3], Ty* _rng, const float _normal[3]) + { + float dir[3]; + randUnitSphere(dir, _rng); + + float DdotN = dir[0]*_normal[0] + + dir[1]*_normal[1] + + dir[2]*_normal[2] + ; + + if (0.0f > DdotN) + { + dir[0] = -dir[0]; + dir[1] = -dir[1]; + dir[2] = -dir[2]; + } + + _result[0] = dir[0]; + _result[1] = dir[1]; + _result[2] = dir[2]; + } + + inline void generateSphereHammersley(void* _data, uint32_t _stride, uint32_t _num, float _scale) + { + uint8_t* data = (uint8_t*)_data; + + for (uint32_t ii = 0; ii < _num; ii++) + { + float tt = 0.0f; + float pp = 0.5; + for (uint32_t jj = ii; jj; jj >>= 1) + { + tt += (jj & 1) ? pp : 0.0f; + pp *= 0.5f; + } + + tt = 2.0f * tt - 1.0f; + + const float phi = (ii + 0.5f) / _num; + const float phirad = phi * 2.0f * pi; + const float st = fsqrt(1.0f-tt*tt) * _scale; + + float* xyz = (float*)data; + data += _stride; + + xyz[0] = st * fcos(phirad); + xyz[1] = st * fsin(phirad); + xyz[2] = tt * _scale; + } + } + + template<typename Rng, typename Ty> + inline void shuffle(Rng* _rng, Ty* _array, uint32_t _num) + { + BX_CHECK(_num != 0, "Number of elements can't be 0!"); + + for (uint32_t ii = 0, num = _num-1; ii < num; ++ii) + { + uint32_t jj = ii + 1 + _rng->gen() % (num - ii); + bx::xchg(_array[ii], _array[jj]); + } + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/sem.h b/3rdparty/bx/include/bx/sem.h index b33ab3721b0..acc2359c363 100644 --- a/3rdparty/bx/include/bx/sem.h +++ b/3rdparty/bx/include/bx/sem.h @@ -7,7 +7,6 @@ #define BX_SEM_H_HEADER_GUARD #include "bx.h" -#include "mutex.h" #if BX_CONFIG_SUPPORTS_THREADING @@ -16,18 +15,19 @@ # include <semaphore.h> # include <time.h> # include <pthread.h> -#elif BX_PLATFORM_XBOXONE -# include <synchapi.h> -#elif BX_PLATFORM_XBOX360 || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT +#elif BX_PLATFORM_XBOX360 || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE # include <windows.h> # include <limits.h> +# if BX_PLATFORM_XBOXONE +# include <synchapi.h> +# endif // BX_PLATFORM_XBOXONE #endif // BX_PLATFORM_ +#include "mutex.h" + namespace bx { -#if BX_PLATFORM_POSIX - -# if BX_CONFIG_SEMAPHORE_PTHREAD + /// class Semaphore { BX_CLASS(Semaphore @@ -36,228 +36,31 @@ namespace bx ); public: - Semaphore() - : m_count(0) - { - int result; - result = pthread_mutex_init(&m_mutex, NULL); - BX_CHECK(0 == result, "pthread_mutex_init %d", result); - - result = pthread_cond_init(&m_cond, NULL); - BX_CHECK(0 == result, "pthread_cond_init %d", result); - - BX_UNUSED(result); - } - - ~Semaphore() - { - int result; - result = pthread_cond_destroy(&m_cond); - BX_CHECK(0 == result, "pthread_cond_destroy %d", result); - - result = pthread_mutex_destroy(&m_mutex); - BX_CHECK(0 == result, "pthread_mutex_destroy %d", result); - - BX_UNUSED(result); - } - - void post(uint32_t _count = 1) - { - int result = pthread_mutex_lock(&m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); - - for (uint32_t ii = 0; ii < _count; ++ii) - { - result = pthread_cond_signal(&m_cond); - BX_CHECK(0 == result, "pthread_cond_signal %d", result); - } - - m_count += _count; - - result = pthread_mutex_unlock(&m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + /// + Semaphore(); - BX_UNUSED(result); - } + /// + ~Semaphore(); - bool wait(int32_t _msecs = -1) - { - int result = pthread_mutex_lock(&m_mutex); - BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + /// + void post(uint32_t _count = 1); -# if BX_PLATFORM_NACL || BX_PLATFORM_OSX - BX_UNUSED(_msecs); - BX_CHECK(-1 == _msecs, "NaCl and OSX don't support pthread_cond_timedwait at this moment."); - while (0 == result - && 0 >= m_count) - { - result = pthread_cond_wait(&m_cond, &m_mutex); - } -# elif BX_PLATFORM_IOS - if (-1 == _msecs) - { - while (0 == result - && 0 >= m_count) - { - result = pthread_cond_wait(&m_cond, &m_mutex); - } - } - else - { - timespec ts; - ts.tv_sec = _msecs/1000; - ts.tv_nsec = (_msecs%1000)*1000; - - while (0 == result - && 0 >= m_count) - { - result = pthread_cond_timedwait_relative_np(&m_cond, &m_mutex, &ts); - } - } -# else - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += _msecs/1000; - ts.tv_nsec += (_msecs%1000)*1000; - - while (0 == result - && 0 >= m_count) - { - result = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); - } -# endif // BX_PLATFORM_NACL || BX_PLATFORM_OSX - bool ok = 0 == result; - - if (ok) - { - --m_count; - } - - result = pthread_mutex_unlock(&m_mutex); - BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); - - BX_UNUSED(result); - - return ok; - } + /// + bool wait(int32_t _msecs = -1); private: +#if BX_PLATFORM_POSIX +# if BX_CONFIG_SEMAPHORE_PTHREAD pthread_mutex_t m_mutex; pthread_cond_t m_cond; int32_t m_count; - }; - # else - - class Semaphore - { - BX_CLASS(Semaphore - , NO_COPY - , NO_ASSIGNMENT - ); - - public: - Semaphore() - { - int32_t result = sem_init(&m_handle, 0, 0); - BX_CHECK(0 == result, "sem_init failed. errno %d", errno); - BX_UNUSED(result); - } - - ~Semaphore() - { - int32_t result = sem_destroy(&m_handle); - BX_CHECK(0 == result, "sem_destroy failed. errno %d", errno); - BX_UNUSED(result); - } - - void post(uint32_t _count = 1) - { - int32_t result; - for (uint32_t ii = 0; ii < _count; ++ii) - { - result = sem_post(&m_handle); - BX_CHECK(0 == result, "sem_post failed. errno %d", errno); - } - BX_UNUSED(result); - } - - bool wait(int32_t _msecs = -1) - { -# if BX_PLATFORM_NACL || BX_PLATFORM_OSX - BX_CHECK(-1 == _msecs, "NaCl and OSX don't support sem_timedwait at this moment."); BX_UNUSED(_msecs); - return 0 == sem_wait(&m_handle); -# else - if (0 > _msecs) - { - int32_t result; - do - { - result = sem_wait(&m_handle); - } // keep waiting when interrupted by a signal handler... - while (-1 == result && EINTR == errno); - BX_CHECK(0 == result, "sem_wait failed. errno %d", errno); - return 0 == result; - } - - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += _msecs/1000; - ts.tv_nsec += (_msecs%1000)*1000; - return 0 == sem_timedwait(&m_handle, &ts); -# endif // BX_PLATFORM_ - } - - private: sem_t m_handle; - }; # endif // BX_CONFIG_SEMAPHORE_PTHREAD - #elif BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT - - class Semaphore - { - BX_CLASS(Semaphore - , NO_COPY - , NO_ASSIGNMENT - ); - - public: - Semaphore() - { -#if BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - m_handle = CreateSemaphoreExW(NULL, 0, LONG_MAX, NULL, 0, SEMAPHORE_ALL_ACCESS); -#else - m_handle = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL); -#endif - BX_CHECK(NULL != m_handle, "Failed to create Semaphore!"); - } - - ~Semaphore() - { - CloseHandle(m_handle); - } - - void post(uint32_t _count = 1) const - { - ReleaseSemaphore(m_handle, _count, NULL); - } - - bool wait(int32_t _msecs = -1) const - { - DWORD milliseconds = (0 > _msecs) ? INFINITE : _msecs; -#if BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - return WAIT_OBJECT_0 == WaitForSingleObjectEx(m_handle, milliseconds, FALSE); -#else - return WAIT_OBJECT_0 == WaitForSingleObject(m_handle, milliseconds); -#endif - } - - private: HANDLE m_handle; - }; - #endif // BX_PLATFORM_ + }; } // namespace bx diff --git a/3rdparty/bx/include/bx/simd256_avx.inl b/3rdparty/bx/include/bx/simd256_avx.inl index 2a31c83f5ae..5eed77ba3af 100644 --- a/3rdparty/bx/include/bx/simd256_avx.inl +++ b/3rdparty/bx/include/bx/simd256_avx.inl @@ -46,7 +46,7 @@ namespace bx template<> BX_SIMD_FORCE_INLINE simd256_avx_t simd_isplat(uint32_t _a) { - const __m256i splat = _mm256_set1_epi32(_a); + const __m256i splat = _mm256_set1_epi32(_a); const simd256_avx_t result = _mm256_castsi256_ps(splat); return result; @@ -55,7 +55,7 @@ namespace bx template<> BX_SIMD_FORCE_INLINE simd256_avx_t simd_itof(simd256_avx_t _a) { - const __m256i itof = _mm256_castps_si256(_a); + const __m256i itof = _mm256_castps_si256(_a); const simd256_avx_t result = _mm256_cvtepi32_ps(itof); return result; @@ -64,7 +64,7 @@ namespace bx template<> BX_SIMD_FORCE_INLINE simd256_avx_t simd_ftoi(simd256_avx_t _a) { - const __m256i ftoi = _mm256_cvtps_epi32(_a); + const __m256i ftoi = _mm256_cvtps_epi32(_a); const simd256_avx_t result = _mm256_castsi256_ps(ftoi); return result; diff --git a/3rdparty/bx/include/bx/string.h b/3rdparty/bx/include/bx/string.h index 44002f55250..eaf27bc983c 100644 --- a/3rdparty/bx/include/bx/string.h +++ b/3rdparty/bx/include/bx/string.h @@ -8,696 +8,234 @@ #include "bx.h" #include <alloca.h> -#include <ctype.h> // tolower #include <stdarg.h> // va_list -#include <stdio.h> // vsnprintf, vsnwprintf -#include <string.h> #include <wchar.h> // wchar_t #include <bx/allocator.h> #include <bx/hash.h> -#ifndef va_copy -# define va_copy(_a, _b) (_a) = (_b) -#endif // va_copy - namespace bx { - /// - inline bool toBool(const char* _str) + /// Non-zero-terminated string view. + class StringView { - char ch = (char)::tolower(_str[0]); - return ch == 't' || ch == '1'; - } + public: + /// + StringView(); - /// Case insensitive string compare. - inline int32_t stricmp(const char* _a, const char* _b) + /// + StringView(const StringView& _rhs); + + /// + StringView& operator=(const StringView& _rhs); + + /// + StringView(const char* _ptr, uint32_t _len = UINT16_MAX); + + /// + void set(const char* _ptr, uint32_t _len = UINT16_MAX); + + /// + void clear(); + + /// + const char* getPtr() const; + + /// + const char* getTerm() const; + + /// + bool isEmpty() const; + + /// + uint32_t getLength() const; + + protected: + const char* m_ptr; + uint32_t m_len; + }; + + /// ASCII string + template<bx::AllocatorI** AllocatorT> + class StringT : public StringView { -#if BX_CRT_MSVC - return ::_stricmp(_a, _b); -#else - return ::strcasecmp(_a, _b); -#endif // BX_COMPILER_ - } + public: + /// + StringT(); + + /// + StringT(const StringT<AllocatorT>& _rhs); + + /// + StringT<AllocatorT>& operator=(const StringT<AllocatorT>& _rhs); + + /// + StringT(const char* _ptr, uint32_t _len = UINT32_MAX); + + /// + StringT(const StringView& _rhs); + + /// + ~StringT(); + + /// + void set(const char* _ptr, uint32_t _len = UINT32_MAX); + + /// + void append(const char* _ptr, uint32_t _len = UINT32_MAX); + + /// + void clear(); + }; /// - inline size_t strnlen(const char* _str, size_t _max) - { - const char* ptr; - for (ptr = _str; 0 < _max && *ptr != '\0'; ++ptr, --_max) {}; - return ptr - _str; - } + bool isSpace(char _ch); + + /// + bool isUpper(char _ch); + + /// + bool isLower(char _ch); + + /// + bool isAlpha(char _ch); + + /// + bool isNumeric(char _ch); + + /// + bool isAlphaNum(char _ch); + + /// + bool isPrint(char _ch); + + /// + char toLower(char _ch); + + /// + char toUpper(char _ch); + + /// + bool toBool(const char* _str); + + /// String compare. + int32_t strncmp(const char* _lhs, const char* _rhs, size_t _max = INT32_MAX); + + /// Case insensitive string compare. + int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max = INT32_MAX); + + /// + size_t strnlen(const char* _str, size_t _max = -1); /// Copy _num characters from string _src to _dst buffer of maximum _dstSize capacity /// including zero terminator. Copy will be terminated with '\0'. - inline size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = -1) - { - BX_CHECK(NULL != _dst, "_dst can't be NULL!"); - BX_CHECK(NULL != _src, "_src can't be NULL!"); - BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num = INT32_MAX); - const size_t len = strnlen(_src, _num); - const size_t max = _dstSize-1; - const size_t num = (len < max ? len : max); - strncpy(_dst, _src, num); - _dst[num] = '\0'; + /// + size_t strlncat(char* _dst, size_t _dstSize, const char* _src, size_t _num = INT32_MAX); + + /// + const char* strnchr(const char* _str, char _ch, size_t _max = INT32_MAX); - return num; - } + /// + const char* strnrchr(const char* _str, char _ch, size_t _max = INT32_MAX); /// Find substring in string. Limit search to _size. - inline const char* strnstr(const char* _str, const char* _find, size_t _size) - { - char first = *_find; - if ('\0' == first) - { - return _str; - } - - const char* cmp = _find + 1; - size_t len = strlen(cmp); - do - { - for (char match = *_str++; match != first && 0 < _size; match = *_str++, --_size) - { - if ('\0' == match) - { - return NULL; - } - } - - if (0 == _size) - { - return NULL; - } - - } while (0 != strncmp(_str, cmp, len) ); - - return --_str; - } - - /// Find substring in string. Case insensitive. - inline const char* stristr(const char* _str, const char* _find) - { - const char* ptr = _str; - - for (size_t len = strlen(_str), searchLen = strlen(_find) - ; len >= searchLen - ; ++ptr, --len) - { - // Find start of the string. - while (tolower(*ptr) != tolower(*_find) ) - { - ++ptr; - --len; - - // Search pattern lenght can't be longer than the string. - if (searchLen > len) - { - return NULL; - } - } - - // Set pointers. - const char* string = ptr; - const char* search = _find; - - // Start comparing. - while (tolower(*string++) == tolower(*search++) ) - { - // If end of the 'search' string is reached, all characters match. - if ('\0' == *search) - { - return ptr; - } - } - } - - return NULL; - } + const char* strnstr(const char* _str, const char* _find, size_t _max = INT32_MAX); /// Find substring in string. Case insensitive. Limit search to _max. - inline const char* stristr(const char* _str, const char* _find, size_t _max) - { - const char* ptr = _str; - - size_t stringLen = strnlen(_str, _max); - const size_t findLen = strlen(_find); - - for (; stringLen >= findLen; ++ptr, --stringLen) - { - // Find start of the string. - while (tolower(*ptr) != tolower(*_find) ) - { - ++ptr; - --stringLen; - - // Search pattern lenght can't be longer than the string. - if (findLen > stringLen) - { - return NULL; - } - } - - // Set pointers. - const char* string = ptr; - const char* search = _find; - - // Start comparing. - while (tolower(*string++) == tolower(*search++) ) - { - // If end of the 'search' string is reached, all characters match. - if ('\0' == *search) - { - return ptr; - } - } - } - - return NULL; - } + const char* stristr(const char* _str, const char* _find, size_t _max = INT32_MAX); /// Find new line. Returns pointer after new line terminator. - inline const char* strnl(const char* _str) - { - for (; '\0' != *_str; _str += strnlen(_str, 1024) ) - { - const char* eol = strnstr(_str, "\r\n", 1024); - if (NULL != eol) - { - return eol + 2; - } - - eol = strnstr(_str, "\n", 1024); - if (NULL != eol) - { - return eol + 1; - } - } - - return _str; - } + const char* strnl(const char* _str); /// Find end of line. Retuns pointer to new line terminator. - inline const char* streol(const char* _str) - { - for (; '\0' != *_str; _str += strnlen(_str, 1024) ) - { - const char* eol = strnstr(_str, "\r\n", 1024); - if (NULL != eol) - { - return eol; - } - - eol = strnstr(_str, "\n", 1024); - if (NULL != eol) - { - return eol; - } - } - - return _str; - } + const char* streol(const char* _str); /// Skip whitespace. - inline const char* strws(const char* _str) - { - for (; isspace(*_str); ++_str) {}; - return _str; - } + const char* strws(const char* _str); /// Skip non-whitespace. - inline const char* strnws(const char* _str) - { - for (; !isspace(*_str); ++_str) {}; - return _str; - } + const char* strnws(const char* _str); /// Skip word. - inline const char* strword(const char* _str) - { - for (char ch = *_str++; isalnum(ch) || '_' == ch; ch = *_str++) {}; - return _str-1; - } + const char* strword(const char* _str); /// Find matching block. - inline const char* strmb(const char* _str, char _open, char _close) - { - int count = 0; - for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++) - { - if (ch == _open) - { - count++; - } - else if (ch == _close) - { - count--; - if (0 == count) - { - return _str-1; - } - } - } - - return NULL; - } + const char* strmb(const char* _str, char _open, char _close); // Normalize string to sane line endings. - inline void eolLF(char* _out, size_t _size, const char* _str) - { - if (0 < _size) - { - char* end = _out + _size - 1; - for (char ch = *_str++; ch != '\0' && _out < end; ch = *_str++) - { - if ('\r' != ch) - { - *_out++ = ch; - } - } - - *_out = '\0'; - } - } + void eolLF(char* _out, size_t _size, const char* _str); // Finds identifier. - inline const char* findIdentifierMatch(const char* _str, const char* _word) - { - size_t len = strlen(_word); - const char* ptr = strstr(_str, _word); - for (; NULL != ptr; ptr = strstr(ptr + len, _word) ) - { - if (ptr != _str) - { - char ch = *(ptr - 1); - if (isalnum(ch) || '_' == ch) - { - continue; - } - } - - char ch = ptr[len]; - if (isalnum(ch) || '_' == ch) - { - continue; - } - - return ptr; - } - - return ptr; - } + const char* findIdentifierMatch(const char* _str, const char* _word); // Finds any identifier from NULL terminated array of identifiers. - inline const char* findIdentifierMatch(const char* _str, const char* _words[]) - { - for (const char* word = *_words; NULL != word; ++_words, word = *_words) - { - const char* match = findIdentifierMatch(_str, word); - if (NULL != match) - { - return match; - } - } - - return NULL; - } + const char* findIdentifierMatch(const char* _str, const char* _words[]); /// Cross platform implementation of vsnprintf that returns number of /// characters which would have been written to the final string if /// enough space had been available. - inline int32_t vsnprintf(char* _str, size_t _count, const char* _format, va_list _argList) - { -#if BX_COMPILER_MSVC - va_list argListCopy; - va_copy(argListCopy, _argList); - int32_t len = ::vsnprintf_s(_str, _count, size_t(-1), _format, argListCopy); - va_end(argListCopy); - return -1 == len ? ::_vscprintf(_format, _argList) : len; -#else - return ::vsnprintf(_str, _count, _format, _argList); -#endif // BX_COMPILER_MSVC - } + int32_t vsnprintf(char* _out, size_t _max, const char* _format, va_list _argList); /// Cross platform implementation of vsnwprintf that returns number of /// characters which would have been written to the final string if /// enough space had been available. - inline int32_t vsnwprintf(wchar_t* _str, size_t _count, const wchar_t* _format, va_list _argList) - { -#if BX_COMPILER_MSVC - va_list argListCopy; - va_copy(argListCopy, _argList); - int32_t len = ::_vsnwprintf_s(_str, _count, size_t(-1), _format, argListCopy); - va_end(argListCopy); - return -1 == len ? ::_vscwprintf(_format, _argList) : len; -#elif defined(__MINGW32__) - return ::vsnwprintf(_str, _count, _format, _argList); -#else - return ::vswprintf(_str, _count, _format, _argList); -#endif // BX_COMPILER_MSVC - } + int32_t vsnwprintf(wchar_t* _out, size_t _max, const wchar_t* _format, va_list _argList); /// - inline int32_t snprintf(char* _str, size_t _count, const char* _format, ...) // BX_PRINTF_ARGS(3, 4) - { - va_list argList; - va_start(argList, _format); - int32_t len = vsnprintf(_str, _count, _format, argList); - va_end(argList); - return len; - } + int32_t snprintf(char* _out, size_t _max, const char* _format, ...); /// - inline int32_t swnprintf(wchar_t* _out, size_t _count, const wchar_t* _format, ...) - { - va_list argList; - va_start(argList, _format); - int32_t len = vsnwprintf(_out, _count, _format, argList); - va_end(argList); - return len; - } + int32_t swnprintf(wchar_t* _out, size_t _max, const wchar_t* _format, ...); /// template <typename Ty> - inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList) - { - char temp[2048]; - - char* out = temp; - int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); - if ( (int32_t)sizeof(temp) < len) - { - out = (char*)alloca(len+1); - len = bx::vsnprintf(out, len, _format, _argList); - } - out[len] = '\0'; - _out.append(out); - } + void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList); /// template <typename Ty> - inline void stringPrintf(Ty& _out, const char* _format, ...) - { - va_list argList; - va_start(argList, _format); - stringPrintfVargs(_out, _format, argList); - va_end(argList); - } + void stringPrintf(Ty& _out, const char* _format, ...); /// Replace all instances of substring. template <typename Ty> - inline Ty replaceAll(const Ty& _str, const char* _from, const char* _to) - { - Ty str = _str; - size_t startPos = 0; - const size_t fromLen = strlen(_from); - const size_t toLen = strlen(_to); - while ( (startPos = str.find(_from, startPos) ) != Ty::npos) - { - str.replace(startPos, fromLen, _to); - startPos += toLen; - } - - return str; - } + Ty replaceAll(const Ty& _str, const char* _from, const char* _to); /// Extract base file name from file path. - inline const char* baseName(const char* _filePath) - { - const char* bs = strrchr(_filePath, '\\'); - const char* fs = strrchr(_filePath, '/'); - const char* slash = (bs > fs ? bs : fs); - const char* colon = strrchr(_filePath, ':'); - const char* basename = slash > colon ? slash : colon; - if (NULL != basename) - { - return basename+1; - } - - return _filePath; - } + const char* baseName(const char* _filePath); /// Convert size in bytes to human readable string. - inline void prettify(char* _out, size_t _count, uint64_t _size) - { - uint8_t idx = 0; - double size = double(_size); - while (_size != (_size&0x7ff) - && idx < 9) - { - _size >>= 10; - size *= 1.0/1024.0; - ++idx; - } - - snprintf(_out, _count, "%0.2f %c%c", size, "BkMGTPEZY"[idx], idx > 0 ? 'B' : '\0'); - } - - /* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ + void prettify(char* _out, size_t _count, uint64_t _size); /// Copy src to string dst of size siz. At most siz-1 characters /// will be copied. Always NUL terminates (unless siz == 0). /// Returns strlen(src); if retval >= siz, truncation occurred. - inline size_t strlcpy(char* _dst, const char* _src, size_t _siz) - { - char* dd = _dst; - const char* ss = _src; - size_t nn = _siz; - - /* Copy as many bytes as will fit */ - if (nn != 0) - { - while (--nn != 0) - { - if ( (*dd++ = *ss++) == '\0') - { - break; - } - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (nn == 0) - { - if (_siz != 0) - { - *dd = '\0'; /* NUL-terminate dst */ - } - - while (*ss++) - { - } - } - - return(ss - _src - 1); /* count does not include NUL */ - } + size_t strlcpy(char* _dst, const char* _src, size_t _max); /// Appends src to string dst of size siz (unlike strncat, siz is the /// full size of dst, not space left). At most siz-1 characters /// will be copied. Always NUL terminates (unless siz <= strlen(dst)). /// Returns strlen(src) + MIN(siz, strlen(initial dst)). /// If retval >= siz, truncation occurred. - inline size_t strlcat(char* _dst, const char* _src, size_t _siz) - { - char* dd = _dst; - const char *s = _src; - size_t nn = _siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (nn-- != 0 && *dd != '\0') - { - dd++; - } - - dlen = dd - _dst; - nn = _siz - dlen; - - if (nn == 0) - { - return(dlen + strlen(s)); - } - - while (*s != '\0') - { - if (nn != 1) - { - *dd++ = *s; - nn--; - } - s++; - } - *dd = '\0'; - - return(dlen + (s - _src)); /* count does not include NUL */ - } - - /// Non-zero-terminated string view. - class StringView - { - public: - StringView() - { - clear(); - } - - StringView(const StringView& _rhs) - { - set(_rhs.m_ptr, _rhs.m_len); - } - - StringView& operator=(const StringView& _rhs) - { - set(_rhs.m_ptr, _rhs.m_len); - return *this; - } - - StringView(const char* _ptr, uint32_t _len = UINT16_MAX) - { - set(_ptr, _len); - } - - void set(const char* _ptr, uint32_t _len = UINT16_MAX) - { - clear(); - - if (NULL != _ptr) - { - uint32_t len = uint32_t(strnlen(_ptr, _len) ); - if (0 != len) - { - m_len = len; - m_ptr = _ptr; - } - } - } - - void clear() - { - m_ptr = ""; - m_len = 0; - } - - const char* getPtr() const - { - return m_ptr; - } - - const char* getTerm() const - { - return m_ptr + m_len; - } - - bool isEmpty() const - { - return 0 == m_len; - } - - uint32_t getLength() const - { - return m_len; - } + size_t strlcat(char* _dst, const char* _src, size_t _max); - protected: - friend uint32_t hashMurmur2A(const StringView& _data); + /// + int32_t toString(char* _out, size_t _max, double _value); - const char* m_ptr; - uint32_t m_len; - }; + /// + int32_t toString(char* _out, size_t _max, int32_t _value, uint32_t _base = 10); - inline uint32_t hashMurmur2A(const StringView& _data) - { - return hashMurmur2A(_data.m_ptr, _data.m_len); - } + /// + int32_t toString(char* _out, size_t _max, uint32_t _value, uint32_t _base = 10); - inline uint32_t hashMurmur2A(const char* _data) - { - return hashMurmur2A(StringView(_data) ); - } + /// + uint32_t hashMurmur2A(const StringView& _data); - /// ASCII string - template<bx::AllocatorI** AllocatorT> - class StringT : public StringView - { - public: - StringT() - : StringView() - { - } - - StringT(const StringT<AllocatorT>& _rhs) - : StringView() - { - set(_rhs.m_ptr, _rhs.m_len); - } - - StringT<AllocatorT>& operator=(const StringT<AllocatorT>& _rhs) - { - set(_rhs.m_ptr, _rhs.m_len); - return *this; - } - - StringT(const char* _ptr, uint32_t _len = UINT32_MAX) - { - set(_ptr, _len); - } - - StringT(const StringView& _rhs) - { - set(_rhs.getPtr(), _rhs.getLength() ); - } - - ~StringT() - { - clear(); - } - - void set(const char* _ptr, uint32_t _len = UINT32_MAX) - { - clear(); - append(_ptr, _len); - } - - void append(const char* _ptr, uint32_t _len = UINT32_MAX) - { - if (0 != _len) - { - uint32_t old = m_len; - uint32_t len = m_len + uint32_t(strnlen(_ptr, _len) ); - char* ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_len ? const_cast<char*>(m_ptr) : NULL, len+1); - m_len = len; - strlncpy(ptr + old, len-old+1, _ptr, _len); - - *const_cast<char**>(&m_ptr) = ptr; - } - } - - void clear() - { - if (0 != m_len) - { - BX_FREE(*AllocatorT, const_cast<char*>(m_ptr) ); - - StringView::clear(); - } - } - }; + /// + uint32_t hashMurmur2A(const char* _data); } // namespace bx +#include "string.inl" + #endif // BX_STRING_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/string.inl b/3rdparty/bx/include/bx/string.inl new file mode 100644 index 00000000000..42f2a6a05b9 --- /dev/null +++ b/3rdparty/bx/include/bx/string.inl @@ -0,0 +1,200 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_STRING_H_HEADER_GUARD +# error "Must be included from bx/string.h!" +#endif // BX_STRING_H_HEADER_GUARD + +#if BX_CRT_MSVC && !defined(va_copy) +# define va_copy(_a, _b) (_a) = (_b) +#endif // BX_CRT_MSVC && !defined(va_copy) + +namespace bx +{ + template <typename Ty> + inline void stringPrintfVargs(Ty& _out, const char* _format, va_list _argList) + { + char temp[2048]; + + char* out = temp; + int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); + if ( (int32_t)sizeof(temp) < len) + { + out = (char*)alloca(len+1); + len = bx::vsnprintf(out, len, _format, _argList); + } + out[len] = '\0'; + _out.append(out); + } + + template <typename Ty> + inline void stringPrintf(Ty& _out, const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + stringPrintfVargs(_out, _format, argList); + va_end(argList); + } + + template <typename Ty> + inline Ty replaceAll(const Ty& _str, const char* _from, const char* _to) + { + Ty str = _str; + size_t startPos = 0; + const size_t fromLen = strlen(_from); + const size_t toLen = strlen(_to); + while ( (startPos = str.find(_from, startPos) ) != Ty::npos) + { + str.replace(startPos, fromLen, _to); + startPos += toLen; + } + + return str; + } + + inline StringView::StringView() + { + clear(); + } + + inline StringView::StringView(const StringView& _rhs) + { + set(_rhs.m_ptr, _rhs.m_len); + } + + inline StringView& StringView::operator=(const StringView& _rhs) + { + set(_rhs.m_ptr, _rhs.m_len); + return *this; + } + + inline StringView::StringView(const char* _ptr, uint32_t _len) + { + set(_ptr, _len); + } + + inline void StringView::set(const char* _ptr, uint32_t _len) + { + clear(); + + if (NULL != _ptr) + { + uint32_t len = uint32_t(strnlen(_ptr, _len) ); + if (0 != len) + { + m_len = len; + m_ptr = _ptr; + } + } + } + + inline void StringView::clear() + { + m_ptr = ""; + m_len = 0; + } + + inline const char* StringView::getPtr() const + { + return m_ptr; + } + + inline const char* StringView::getTerm() const + { + return m_ptr + m_len; + } + + inline bool StringView::isEmpty() const + { + return 0 == m_len; + } + + inline uint32_t StringView::getLength() const + { + return m_len; + } + + inline uint32_t hashMurmur2A(const StringView& _data) + { + return hashMurmur2A(_data.getPtr(), _data.getLength() ); + } + + inline uint32_t hashMurmur2A(const char* _data) + { + return hashMurmur2A(StringView(_data) ); + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>::StringT() + : StringView() + { + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>::StringT(const StringT<AllocatorT>& _rhs) + : StringView() + { + set(_rhs.m_ptr, _rhs.m_len); + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>& StringT<AllocatorT>::operator=(const StringT<AllocatorT>& _rhs) + { + set(_rhs.m_ptr, _rhs.m_len); + return *this; + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>::StringT(const char* _ptr, uint32_t _len) + { + set(_ptr, _len); + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>::StringT(const StringView& _rhs) + { + set(_rhs.getPtr(), _rhs.getLength() ); + } + + template<bx::AllocatorI** AllocatorT> + inline StringT<AllocatorT>::~StringT() + { + clear(); + } + + template<bx::AllocatorI** AllocatorT> + inline void StringT<AllocatorT>::set(const char* _ptr, uint32_t _len) + { + clear(); + append(_ptr, _len); + } + + template<bx::AllocatorI** AllocatorT> + inline void StringT<AllocatorT>::append(const char* _ptr, uint32_t _len) + { + if (0 != _len) + { + uint32_t old = m_len; + uint32_t len = m_len + uint32_t(strnlen(_ptr, _len) ); + char* ptr = (char*)BX_REALLOC(*AllocatorT, 0 != m_len ? const_cast<char*>(m_ptr) : NULL, len+1); + m_len = len; + strlncpy(ptr + old, len-old+1, _ptr, _len); + + *const_cast<char**>(&m_ptr) = ptr; + } + } + + template<bx::AllocatorI** AllocatorT> + inline void StringT<AllocatorT>::clear() + { + if (0 != m_len) + { + BX_FREE(*AllocatorT, const_cast<char*>(m_ptr) ); + + StringView::clear(); + } + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/thread.h b/3rdparty/bx/include/bx/thread.h index 8514a704280..95152367f02 100644 --- a/3rdparty/bx/include/bx/thread.h +++ b/3rdparty/bx/include/bx/thread.h @@ -6,6 +6,8 @@ #ifndef BX_THREAD_H_HEADER_GUARD #define BX_THREAD_H_HEADER_GUARD +#include "bx.h" + #if BX_PLATFORM_POSIX # include <pthread.h> # if defined(__FreeBSD__) @@ -26,8 +28,10 @@ using namespace Windows::System::Threading; namespace bx { + /// typedef int32_t (*ThreadFn)(void* _userData); + /// class Thread { BX_CLASS(Thread @@ -36,205 +40,36 @@ namespace bx ); public: - Thread() -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - : m_handle(INVALID_HANDLE_VALUE) - , m_threadId(UINT32_MAX) -#elif BX_PLATFORM_POSIX - : m_handle(0) -#endif // BX_PLATFORM_ - , m_fn(NULL) - , m_userData(NULL) - , m_stackSize(0) - , m_exitCode(0 /*EXIT_SUCCESS*/) - , m_running(false) - { - } + /// + Thread(); - virtual ~Thread() - { - if (m_running) - { - shutdown(); - } - } + /// + virtual ~Thread(); - void init(ThreadFn _fn, void* _userData = NULL, uint32_t _stackSize = 0, const char* _name = NULL) - { - BX_CHECK(!m_running, "Already running!"); + /// + void init(ThreadFn _fn, void* _userData = NULL, uint32_t _stackSize = 0, const char* _name = NULL); - m_fn = _fn; - m_userData = _userData; - m_stackSize = _stackSize; - m_running = true; + /// + void shutdown(); -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE - m_handle = ::CreateThread(NULL - , m_stackSize - , (LPTHREAD_START_ROUTINE)threadFunc - , this - , 0 - , NULL - ); -#elif BX_PLATFORM_WINRT - m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); - auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) - { - m_exitCode = threadFunc(this); - SetEvent(m_handle); - }, CallbackContext::Any); + /// + bool isRunning() const; - ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced); -#elif BX_PLATFORM_POSIX - int result; - BX_UNUSED(result); - - pthread_attr_t attr; - result = pthread_attr_init(&attr); - BX_CHECK(0 == result, "pthread_attr_init failed! %d", result); - - if (0 != m_stackSize) - { - result = pthread_attr_setstacksize(&attr, m_stackSize); - BX_CHECK(0 == result, "pthread_attr_setstacksize failed! %d", result); - } - -// sched_param sched; -// sched.sched_priority = 0; -// result = pthread_attr_setschedparam(&attr, &sched); -// BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); - - result = pthread_create(&m_handle, &attr, &threadFunc, this); - BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); -#else -# error "Not implemented!" -#endif // BX_PLATFORM_ + /// + int32_t getExitCode() const; - m_sem.wait(); - - if (NULL != _name) - { - setThreadName(_name); - } - } - - void shutdown() - { - BX_CHECK(m_running, "Not running!"); -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 - WaitForSingleObject(m_handle, INFINITE); - GetExitCodeThread(m_handle, (DWORD*)&m_exitCode); - CloseHandle(m_handle); - m_handle = INVALID_HANDLE_VALUE; -#elif BX_PLATFORM_WINRT - WaitForSingleObjectEx(m_handle, INFINITE, FALSE); - CloseHandle(m_handle); - m_handle = INVALID_HANDLE_VALUE; -#elif BX_PLATFORM_POSIX - union - { - void* ptr; - int32_t i; - } cast; - pthread_join(m_handle, &cast.ptr); - m_exitCode = cast.i; - m_handle = 0; -#endif // BX_PLATFORM_ - m_running = false; - } - - bool isRunning() const - { - return m_running; - } - - int32_t getExitCode() const - { - return m_exitCode; - } - - void setThreadName(const char* _name) - { -#if BX_PLATFORM_OSX || BX_PLATFORM_IOS - pthread_setname_np(_name); -#elif (BX_CRT_GLIBC >= 21200) && ! BX_PLATFORM_HURD - pthread_setname_np(m_handle, _name); -#elif BX_PLATFORM_LINUX - prctl(PR_SET_NAME,_name, 0, 0, 0); -#elif BX_PLATFORM_BSD -# ifdef __NetBSD__ - pthread_setname_np(m_handle, "%s", (void*)_name); -# else - pthread_set_name_np(m_handle, _name); -# endif // __NetBSD__ -#elif BX_PLATFORM_WINDOWS && BX_COMPILER_MSVC -# pragma pack(push, 8) - struct ThreadName - { - DWORD type; - LPCSTR name; - DWORD id; - DWORD flags; - }; -# pragma pack(pop) - ThreadName tn; - tn.type = 0x1000; - tn.name = _name; - tn.id = m_threadId; - tn.flags = 0; - - __try - { - RaiseException(0x406d1388 - , 0 - , sizeof(tn)/4 - , reinterpret_cast<ULONG_PTR*>(&tn) - ); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } -#else - BX_UNUSED(_name); -#endif // BX_PLATFORM_ - } + /// + void setThreadName(const char* _name); private: - int32_t entry() - { -#if BX_PLATFORM_WINDOWS - m_threadId = ::GetCurrentThreadId(); -#endif // BX_PLATFORM_WINDOWS - - m_sem.post(); - return m_fn(m_userData); - } - -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_WINRT - static DWORD WINAPI threadFunc(LPVOID _arg) - { - Thread* thread = (Thread*)_arg; - int32_t result = thread->entry(); - return result; - } -#else - static void* threadFunc(void* _arg) - { - Thread* thread = (Thread*)_arg; - union - { - void* ptr; - int32_t i; - } cast; - cast.i = thread->entry(); - return cast.ptr; - } -#endif // BX_PLATFORM_ + int32_t entry(); #if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + static DWORD WINAPI threadFunc(LPVOID _arg); HANDLE m_handle; DWORD m_threadId; #elif BX_PLATFORM_POSIX + static void* threadFunc(void* _arg); pthread_t m_handle; #endif // BX_PLATFORM_ @@ -246,71 +81,34 @@ namespace bx bool m_running; }; -#if BX_PLATFORM_WINDOWS + /// class TlsData { public: - TlsData() - { - m_id = TlsAlloc(); - BX_CHECK(TLS_OUT_OF_INDEXES != m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); - } + /// + TlsData(); - ~TlsData() - { - BOOL result = TlsFree(m_id); - BX_CHECK(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); - } + /// + ~TlsData(); - void* get() const - { - return TlsGetValue(m_id); - } + /// + void* get() const; - void set(void* _ptr) - { - TlsSetValue(m_id, _ptr); - } + /// + void set(void* _ptr); private: +#if BX_PLATFORM_WINDOWS uint32_t m_id; - }; - #elif !(BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT) - - class TlsData - { - public: - TlsData() - { - int result = pthread_key_create(&m_id, NULL); - BX_CHECK(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); - } - - ~TlsData() - { - int result = pthread_key_delete(m_id); - BX_CHECK(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); - } - - void* get() const - { - return pthread_getspecific(m_id); - } - - void set(void* _ptr) - { - int result = pthread_setspecific(m_id, _ptr); - BX_CHECK(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); - } - - private: pthread_key_t m_id; - }; #endif // BX_PLATFORM_* + }; } // namespace bx #endif // BX_CONFIG_SUPPORTS_THREADING +#include "thread.inl" + #endif // BX_THREAD_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/thread.inl b/3rdparty/bx/include/bx/thread.inl new file mode 100644 index 00000000000..38fc49d0c3a --- /dev/null +++ b/3rdparty/bx/include/bx/thread.inl @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_THREAD_H_HEADER_GUARD +# error "Must be included from bx/thread.h!" +#endif // BX_THREAD_H_HEADER_GUARD + +#if BX_CONFIG_SUPPORTS_THREADING + +namespace bx +{ +#if BX_PLATFORM_WINDOWS + inline TlsData::TlsData() + { + m_id = TlsAlloc(); + BX_CHECK(TLS_OUT_OF_INDEXES != m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() ); + } + + inline TlsData::~TlsData() + { + BOOL result = TlsFree(m_id); + BX_CHECK(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result); + } + + inline void* TlsData::get() const + { + return TlsGetValue(m_id); + } + + inline void TlsData::set(void* _ptr) + { + TlsSetValue(m_id, _ptr); + } + +#elif !(BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT) + + inline TlsData::TlsData() + { + int result = pthread_key_create(&m_id, NULL); + BX_CHECK(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result); + } + + inline TlsData::~TlsData() + { + int result = pthread_key_delete(m_id); + BX_CHECK(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result); + } + + inline void* TlsData::get() const + { + return pthread_getspecific(m_id); + } + + inline void TlsData::set(void* _ptr) + { + int result = pthread_setspecific(m_id, _ptr); + BX_CHECK(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result); + } +#endif // BX_PLATFORM_* + +} // namespace bx + +#endif // BX_CONFIG_SUPPORTS_THREADING diff --git a/3rdparty/bx/include/bx/timer.h b/3rdparty/bx/include/bx/timer.h index 622e184e968..7b01e2c9974 100644 --- a/3rdparty/bx/include/bx/timer.h +++ b/3rdparty/bx/include/bx/timer.h @@ -8,55 +8,16 @@ #include "bx.h" -#if BX_PLATFORM_ANDROID -# include <time.h> // clock, clock_gettime -#elif BX_PLATFORM_EMSCRIPTEN -# include <emscripten.h> -#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT -# include <windows.h> -#else -# include <sys/time.h> // gettimeofday -#endif // BX_PLATFORM_ - namespace bx { - inline int64_t getHPCounter() - { -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - LARGE_INTEGER li; - // Performance counter value may unexpectedly leap forward - // http://support.microsoft.com/kb/274323 - QueryPerformanceCounter(&li); - int64_t i64 = li.QuadPart; -#elif BX_PLATFORM_ANDROID - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - int64_t i64 = now.tv_sec*INT64_C(1000000000) + now.tv_nsec; -#elif BX_PLATFORM_EMSCRIPTEN - int64_t i64 = int64_t(1000.0f * emscripten_get_now() ); -#else - struct timeval now; - gettimeofday(&now, 0); - int64_t i64 = now.tv_sec*INT64_C(1000000) + now.tv_usec; -#endif // BX_PLATFORM_ - return i64; - } + /// + int64_t getHPCounter(); - inline int64_t getHPFrequency() - { -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - return li.QuadPart; -#elif BX_PLATFORM_ANDROID - return INT64_C(1000000000); -#elif BX_PLATFORM_EMSCRIPTEN - return INT64_C(1000000); -#else - return INT64_C(1000000); -#endif // BX_PLATFORM_ - } + /// + int64_t getHPFrequency(); } // namespace bx +#include "timer.inl" + #endif // BX_TIMER_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/timer.inl b/3rdparty/bx/include/bx/timer.inl new file mode 100644 index 00000000000..d1c609f571a --- /dev/null +++ b/3rdparty/bx/include/bx/timer.inl @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#ifndef BX_TIMER_H_HEADER_GUARD +# error "Must be included from bx/timer.h!" +#endif // BX_TIMER_H_HEADER_GUARD + +#include "bx.h" + +#if BX_PLATFORM_ANDROID +# include <time.h> // clock, clock_gettime +#elif BX_PLATFORM_EMSCRIPTEN +# include <emscripten.h> +#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT +# include <windows.h> +#else +# include <sys/time.h> // gettimeofday +#endif // BX_PLATFORM_ + +namespace bx +{ + inline int64_t getHPCounter() + { +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + LARGE_INTEGER li; + // Performance counter value may unexpectedly leap forward + // http://support.microsoft.com/kb/274323 + QueryPerformanceCounter(&li); + int64_t i64 = li.QuadPart; +#elif BX_PLATFORM_ANDROID + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + int64_t i64 = now.tv_sec*INT64_C(1000000000) + now.tv_nsec; +#elif BX_PLATFORM_EMSCRIPTEN + int64_t i64 = int64_t(1000.0f * emscripten_get_now() ); +#else + struct timeval now; + gettimeofday(&now, 0); + int64_t i64 = now.tv_sec*INT64_C(1000000) + now.tv_usec; +#endif // BX_PLATFORM_ + return i64; + } + + inline int64_t getHPFrequency() + { +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + LARGE_INTEGER li; + QueryPerformanceFrequency(&li); + return li.QuadPart; +#elif BX_PLATFORM_ANDROID + return INT64_C(1000000000); +#elif BX_PLATFORM_EMSCRIPTEN + return INT64_C(1000000); +#else + return INT64_C(1000000); +#endif // BX_PLATFORM_ + } + +} // namespace bx diff --git a/3rdparty/bx/include/bx/tokenizecmd.h b/3rdparty/bx/include/bx/tokenizecmd.h deleted file mode 100644 index 0fe2e00b67a..00000000000 --- a/3rdparty/bx/include/bx/tokenizecmd.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2012-2017 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause - */ - -#ifndef BX_TOKENIZE_CMD_H_HEADER_GUARD -#define BX_TOKENIZE_CMD_H_HEADER_GUARD - -#include <stdint.h> -#include <stdio.h> -#include <ctype.h> - -namespace bx -{ - // Reference: - // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx - static inline const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int& _argc, char* _argv[], int _maxArgvs, char _term = '\0') - { - int argc = 0; - const char* curr = _commandLine; - char* currOut = _buffer; - char term = ' '; - bool sub = false; - - enum ParserState - { - SkipWhitespace, - SetTerm, - Copy, - Escape, - End, - }; - - ParserState state = SkipWhitespace; - - while ('\0' != *curr - && _term != *curr - && argc < _maxArgvs) - { - switch (state) - { - case SkipWhitespace: - for (; isspace(*curr); ++curr) {}; // skip whitespace - state = SetTerm; - break; - - case SetTerm: - if ('"' == *curr) - { - term = '"'; - ++curr; // skip begining quote - } - else - { - term = ' '; - } - - _argv[argc] = currOut; - ++argc; - - state = Copy; - break; - - case Copy: - if ('\\' == *curr) - { - state = Escape; - } - else if ('"' == *curr - && '"' != term) - { - sub = !sub; - } - else if (isspace(*curr) && !sub) - { - state = End; - } - else if (term != *curr || sub) - { - *currOut = *curr; - ++currOut; - } - else - { - state = End; - } - ++curr; - break; - - case Escape: - { - const char* start = --curr; - for (; '\\' == *curr; ++curr) {}; - - if ('"' != *curr) - { - int count = (int)(curr-start); - - curr = start; - for (int ii = 0; ii < count; ++ii) - { - *currOut = *curr; - ++currOut; - ++curr; - } - } - else - { - curr = start+1; - *currOut = *curr; - ++currOut; - ++curr; - } - } - state = Copy; - break; - - case End: - *currOut = '\0'; - ++currOut; - state = SkipWhitespace; - break; - } - } - - *currOut = '\0'; - if (0 < argc - && '\0' == _argv[argc-1][0]) - { - --argc; - } - - _bufferSize = (uint32_t)(currOut - _buffer); - _argc = argc; - - if ('\0' != *curr) - { - ++curr; - } - - return curr; - } - -} // namespace bx - -#endif // TOKENIZE_CMD_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/uint32_t.h b/3rdparty/bx/include/bx/uint32_t.h index a7d6c45ad90..d3b3069fe92 100644 --- a/3rdparty/bx/include/bx/uint32_t.h +++ b/3rdparty/bx/include/bx/uint32_t.h @@ -3,26 +3,6 @@ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ -// Copyright 2006 Mike Acton <macton@gmail.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE - #ifndef BX_UINT32_T_H_HEADER_GUARD #define BX_UINT32_T_H_HEADER_GUARD @@ -30,9 +10,6 @@ #if BX_COMPILER_MSVC # if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT -# include <math.h> // math.h is included because VS bitches: - // warning C4985: 'ceil': attributes not present on previous declaration. - // must be included before intrin.h. # include <intrin.h> # pragma intrinsic(_BitScanForward) # pragma intrinsic(_BitScanReverse) @@ -50,756 +27,264 @@ namespace bx { - inline uint32_t uint32_li(uint32_t _a) - { - return _a; - } - - inline uint32_t uint32_dec(uint32_t _a) - { - return _a - 1; - } - - inline uint32_t uint32_inc(uint32_t _a) - { - return _a + 1; - } - - inline uint32_t uint32_not(uint32_t _a) - { - return ~_a; - } - - inline uint32_t uint32_neg(uint32_t _a) - { - return -(int32_t)_a; - } - - inline uint32_t uint32_ext(uint32_t _a) - { - return ( (int32_t)_a)>>31; - } - - inline uint32_t uint32_and(uint32_t _a, uint32_t _b) - { - return _a & _b; - } - - inline uint32_t uint32_andc(uint32_t _a, uint32_t _b) - { - return _a & ~_b; - } - - inline uint32_t uint32_xor(uint32_t _a, uint32_t _b) - { - return _a ^ _b; - } - - inline uint32_t uint32_xorl(uint32_t _a, uint32_t _b) - { - return !_a != !_b; - } - - inline uint32_t uint32_or(uint32_t _a, uint32_t _b) - { - return _a | _b; - } - - inline uint32_t uint32_orc(uint32_t _a, uint32_t _b) - { - return _a | ~_b; - } - - inline uint32_t uint32_sll(uint32_t _a, int _sa) - { - return _a << _sa; - } - - inline uint32_t uint32_srl(uint32_t _a, int _sa) - { - return _a >> _sa; - } - - inline uint32_t uint32_sra(uint32_t _a, int _sa) - { - return ( (int32_t)_a) >> _sa; - } - - inline uint32_t uint32_rol(uint32_t _a, int _sa) - { - return ( _a << _sa) | (_a >> (32-_sa) ); - } - - inline uint32_t uint32_ror(uint32_t _a, int _sa) - { - return ( _a >> _sa) | (_a << (32-_sa) ); - } - - inline uint32_t uint32_add(uint32_t _a, uint32_t _b) - { - return _a + _b; - } - - inline uint32_t uint32_sub(uint32_t _a, uint32_t _b) - { - return _a - _b; - } - - inline uint32_t uint32_mul(uint32_t _a, uint32_t _b) - { - return _a * _b; - } - - inline uint32_t uint32_div(uint32_t _a, uint32_t _b) - { - return (_a / _b); - } - - inline uint32_t uint32_mod(uint32_t _a, uint32_t _b) - { - return (_a % _b); - } - - inline uint32_t uint32_cmpeq(uint32_t _a, uint32_t _b) - { - return -(_a == _b); - } - - inline uint32_t uint32_cmpneq(uint32_t _a, uint32_t _b) - { - return -(_a != _b); - } - - inline uint32_t uint32_cmplt(uint32_t _a, uint32_t _b) - { - return -(_a < _b); - } - - inline uint32_t uint32_cmple(uint32_t _a, uint32_t _b) - { - return -(_a <= _b); - } - - inline uint32_t uint32_cmpgt(uint32_t _a, uint32_t _b) - { - return -(_a > _b); - } - - inline uint32_t uint32_cmpge(uint32_t _a, uint32_t _b) - { - return -(_a >= _b); - } - - inline uint32_t uint32_setnz(uint32_t _a) - { - return -!!_a; - } - - inline uint32_t uint32_satadd(uint32_t _a, uint32_t _b) - { - const uint32_t add = uint32_add(_a, _b); - const uint32_t lt = uint32_cmplt(add, _a); - const uint32_t result = uint32_or(add, lt); - - return result; - } - - inline uint32_t uint32_satsub(uint32_t _a, uint32_t _b) - { - const uint32_t sub = uint32_sub(_a, _b); - const uint32_t le = uint32_cmple(sub, _a); - const uint32_t result = uint32_and(sub, le); - - return result; - } - - inline uint32_t uint32_satmul(uint32_t _a, uint32_t _b) - { - const uint64_t mul = (uint64_t)_a * (uint64_t)_b; - const uint32_t hi = mul >> 32; - const uint32_t nz = uint32_setnz(hi); - const uint32_t result = uint32_or(uint32_t(mul), nz); - - return result; - } - - inline uint32_t uint32_sels(uint32_t test, uint32_t _a, uint32_t _b) - { - const uint32_t mask = uint32_ext(test); - const uint32_t sel_a = uint32_and(_a, mask); - const uint32_t sel_b = uint32_andc(_b, mask); - const uint32_t result = uint32_or(sel_a, sel_b); - - return (result); - } - - inline uint32_t uint32_selb(uint32_t _mask, uint32_t _a, uint32_t _b) - { - const uint32_t sel_a = uint32_and(_a, _mask); - const uint32_t sel_b = uint32_andc(_b, _mask); - const uint32_t result = uint32_or(sel_a, sel_b); - - return (result); - } - - inline uint32_t uint32_imin(uint32_t _a, uint32_t _b) - { - const uint32_t a_sub_b = uint32_sub(_a, _b); - const uint32_t result = uint32_sels(a_sub_b, _a, _b); - - return result; - } - - inline uint32_t uint32_imax(uint32_t _a, uint32_t _b) - { - const uint32_t b_sub_a = uint32_sub(_b, _a); - const uint32_t result = uint32_sels(b_sub_a, _a, _b); - - return result; - } - - inline uint32_t uint32_min(uint32_t _a, uint32_t _b) - { - return _a > _b ? _b : _a; - } - - inline uint32_t uint32_min(uint32_t _a, uint32_t _b, uint32_t _c) - { - return uint32_min(_a, uint32_min(_b, _c) ); - } - - inline uint32_t uint32_max(uint32_t _a, uint32_t _b) - { - return _a > _b ? _a : _b; - } - - inline uint32_t uint32_max(uint32_t _a, uint32_t _b, uint32_t _c) - { - return uint32_max(_a, uint32_max(_b, _c) ); - } - - inline uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max) - { - const uint32_t tmp = uint32_max(_a, _min); - const uint32_t result = uint32_min(tmp, _max); - - return result; - } - - inline uint32_t uint32_iclamp(uint32_t _a, uint32_t _min, uint32_t _max) - { - const uint32_t tmp = uint32_imax(_a, _min); - const uint32_t result = uint32_imin(tmp, _max); - - return result; - } - - inline uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max) - { - const uint32_t inc = uint32_inc(_val); - const uint32_t max_diff = uint32_sub(_max, _val); - const uint32_t neg_max_diff = uint32_neg(max_diff); - const uint32_t max_or = uint32_or(max_diff, neg_max_diff); - const uint32_t max_diff_nz = uint32_ext(max_or); - const uint32_t result = uint32_selb(max_diff_nz, inc, _min); - - return result; - } - - inline uint32_t uint32_decwrap(uint32_t _val, uint32_t _min, uint32_t _max) - { - const uint32_t dec = uint32_dec(_val); - const uint32_t min_diff = uint32_sub(_min, _val); - const uint32_t neg_min_diff = uint32_neg(min_diff); - const uint32_t min_or = uint32_or(min_diff, neg_min_diff); - const uint32_t min_diff_nz = uint32_ext(min_or); - const uint32_t result = uint32_selb(min_diff_nz, dec, _max); - - return result; - } - - inline uint32_t uint32_cntbits_ref(uint32_t _val) - { - const uint32_t tmp0 = uint32_srl(_val, 1); - const uint32_t tmp1 = uint32_and(tmp0, 0x55555555); - const uint32_t tmp2 = uint32_sub(_val, tmp1); - const uint32_t tmp3 = uint32_and(tmp2, 0xc30c30c3); - const uint32_t tmp4 = uint32_srl(tmp2, 2); - const uint32_t tmp5 = uint32_and(tmp4, 0xc30c30c3); - const uint32_t tmp6 = uint32_srl(tmp2, 4); - const uint32_t tmp7 = uint32_and(tmp6, 0xc30c30c3); - const uint32_t tmp8 = uint32_add(tmp3, tmp5); - const uint32_t tmp9 = uint32_add(tmp7, tmp8); - const uint32_t tmpA = uint32_srl(tmp9, 6); - const uint32_t tmpB = uint32_add(tmp9, tmpA); - const uint32_t tmpC = uint32_srl(tmpB, 12); - const uint32_t tmpD = uint32_srl(tmpB, 24); - const uint32_t tmpE = uint32_add(tmpB, tmpC); - const uint32_t tmpF = uint32_add(tmpD, tmpE); - const uint32_t result = uint32_and(tmpF, 0x3f); - - return result; - } + /// + uint32_t uint32_li(uint32_t _a); + + /// + uint32_t uint32_dec(uint32_t _a); + + /// + uint32_t uint32_inc(uint32_t _a); + + /// + uint32_t uint32_not(uint32_t _a); + + /// + uint32_t uint32_neg(uint32_t _a); + + /// + uint32_t uint32_ext(uint32_t _a); + + /// + uint32_t uint32_and(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_andc(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_xor(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_xorl(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_or(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_orc(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_sll(uint32_t _a, int _sa); + + /// + uint32_t uint32_srl(uint32_t _a, int _sa); + + /// + uint32_t uint32_sra(uint32_t _a, int _sa); + + /// + uint32_t uint32_rol(uint32_t _a, int _sa); + + /// + uint32_t uint32_ror(uint32_t _a, int _sa); + + /// + uint32_t uint32_add(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_sub(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_mul(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_div(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_mod(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmpeq(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmpneq(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmplt(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmple(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmpgt(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_cmpge(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_setnz(uint32_t _a); + + /// + uint32_t uint32_satadd(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_satsub(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_satmul(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_sels(uint32_t test, uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_selb(uint32_t _mask, uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_imin(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_imax(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_min(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_min(uint32_t _a, uint32_t _b, uint32_t _c); + + /// + uint32_t uint32_max(uint32_t _a, uint32_t _b); + + /// + uint32_t uint32_max(uint32_t _a, uint32_t _b, uint32_t _c); + + /// + uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max); + + /// + uint32_t uint32_iclamp(uint32_t _a, uint32_t _min, uint32_t _max); + + /// + uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max); + + /// + uint32_t uint32_decwrap(uint32_t _val, uint32_t _min, uint32_t _max); + + /// + uint32_t uint32_cntbits_ref(uint32_t _val); /// Count number of bits set. - inline uint32_t uint32_cntbits(uint32_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_popcount(_val); -#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS - return __popcnt(_val); -#else - return uint32_cntbits_ref(_val); -#endif // BX_COMPILER_ - } - - inline uint32_t uint32_cntlz_ref(uint32_t _val) - { - const uint32_t tmp0 = uint32_srl(_val, 1); - const uint32_t tmp1 = uint32_or(tmp0, _val); - const uint32_t tmp2 = uint32_srl(tmp1, 2); - const uint32_t tmp3 = uint32_or(tmp2, tmp1); - const uint32_t tmp4 = uint32_srl(tmp3, 4); - const uint32_t tmp5 = uint32_or(tmp4, tmp3); - const uint32_t tmp6 = uint32_srl(tmp5, 8); - const uint32_t tmp7 = uint32_or(tmp6, tmp5); - const uint32_t tmp8 = uint32_srl(tmp7, 16); - const uint32_t tmp9 = uint32_or(tmp8, tmp7); - const uint32_t tmpA = uint32_not(tmp9); - const uint32_t result = uint32_cntbits(tmpA); - - return result; - } + /// + uint32_t uint32_cntbits(uint32_t _val); + + /// + uint32_t uint32_cntlz_ref(uint32_t _val); /// Count number of leading zeros. - inline uint32_t uint32_cntlz(uint32_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_clz(_val); -#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS - unsigned long index; - _BitScanReverse(&index, _val); - return 31 - index; -#else - return uint32_cntlz_ref(_val); -#endif // BX_COMPILER_ - } - - inline uint32_t uint32_cnttz_ref(uint32_t _val) - { - const uint32_t tmp0 = uint32_not(_val); - const uint32_t tmp1 = uint32_dec(_val); - const uint32_t tmp2 = uint32_and(tmp0, tmp1); - const uint32_t result = uint32_cntbits(tmp2); - - return result; - } - - inline uint32_t uint32_cnttz(uint32_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_ctz(_val); -#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS - unsigned long index; - _BitScanForward(&index, _val); - return index; -#else - return uint32_cnttz_ref(_val); -#endif // BX_COMPILER_ - } + /// + uint32_t uint32_cntlz(uint32_t _val); + + /// + uint32_t uint32_cnttz_ref(uint32_t _val); + + /// + uint32_t uint32_cnttz(uint32_t _val); // shuffle: // ---- ---- ---- ---- fedc ba98 7654 3210 // to: // -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 - inline uint32_t uint32_part1by1(uint32_t _a) - { - const uint32_t val = uint32_and(_a, 0xffff); + uint32_t uint32_part1by1(uint32_t _a); - const uint32_t tmp0 = uint32_sll(val, 8); - const uint32_t tmp1 = uint32_xor(val, tmp0); - const uint32_t tmp2 = uint32_and(tmp1, 0x00ff00ff); + // shuffle: + // ---- ---- ---- ---- ---- --98 7654 3210 + // to: + // ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 + /// + uint32_t uint32_part1by2(uint32_t _a); - const uint32_t tmp3 = uint32_sll(tmp2, 4); - const uint32_t tmp4 = uint32_xor(tmp2, tmp3); - const uint32_t tmp5 = uint32_and(tmp4, 0x0f0f0f0f); + /// + uint32_t uint32_testpow2(uint32_t _a); - const uint32_t tmp6 = uint32_sll(tmp5, 2); - const uint32_t tmp7 = uint32_xor(tmp5, tmp6); - const uint32_t tmp8 = uint32_and(tmp7, 0x33333333); + /// + uint32_t uint32_nextpow2(uint32_t _a); - const uint32_t tmp9 = uint32_sll(tmp8, 1); - const uint32_t tmpA = uint32_xor(tmp8, tmp9); - const uint32_t result = uint32_and(tmpA, 0x55555555); + /// + uint16_t halfFromFloat(float _a); - return result; - } + /// + float halfToFloat(uint16_t _a); - // shuffle: - // ---- ---- ---- ---- ---- --98 7654 3210 - // to: - // ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 - inline uint32_t uint32_part1by2(uint32_t _a) - { - const uint32_t val = uint32_and(_a, 0x3ff); - - const uint32_t tmp0 = uint32_sll(val, 16); - const uint32_t tmp1 = uint32_xor(val, tmp0); - const uint32_t tmp2 = uint32_and(tmp1, 0xff0000ff); - - const uint32_t tmp3 = uint32_sll(tmp2, 8); - const uint32_t tmp4 = uint32_xor(tmp2, tmp3); - const uint32_t tmp5 = uint32_and(tmp4, 0x0300f00f); - - const uint32_t tmp6 = uint32_sll(tmp5, 4); - const uint32_t tmp7 = uint32_xor(tmp5, tmp6); - const uint32_t tmp8 = uint32_and(tmp7, 0x030c30c3); - - const uint32_t tmp9 = uint32_sll(tmp8, 2); - const uint32_t tmpA = uint32_xor(tmp8, tmp9); - const uint32_t result = uint32_and(tmpA, 0x09249249); - - return result; - } - - inline uint32_t uint32_testpow2(uint32_t _a) - { - const uint32_t tmp0 = uint32_not(_a); - const uint32_t tmp1 = uint32_inc(tmp0); - const uint32_t tmp2 = uint32_and(_a, tmp1); - const uint32_t tmp3 = uint32_cmpeq(tmp2, _a); - const uint32_t tmp4 = uint32_cmpneq(_a, 0); - const uint32_t result = uint32_and(tmp3, tmp4); - - return result; - } - - inline uint32_t uint32_nextpow2(uint32_t _a) - { - const uint32_t tmp0 = uint32_dec(_a); - const uint32_t tmp1 = uint32_srl(tmp0, 1); - const uint32_t tmp2 = uint32_or(tmp0, tmp1); - const uint32_t tmp3 = uint32_srl(tmp2, 2); - const uint32_t tmp4 = uint32_or(tmp2, tmp3); - const uint32_t tmp5 = uint32_srl(tmp4, 4); - const uint32_t tmp6 = uint32_or(tmp4, tmp5); - const uint32_t tmp7 = uint32_srl(tmp6, 8); - const uint32_t tmp8 = uint32_or(tmp6, tmp7); - const uint32_t tmp9 = uint32_srl(tmp8, 16); - const uint32_t tmpA = uint32_or(tmp8, tmp9); - const uint32_t result = uint32_inc(tmpA); - - return result; - } - - inline uint16_t halfFromFloat(float _a) - { - union { uint32_t ui; float flt; } ftou; - ftou.flt = _a; - - const uint32_t one = uint32_li(0x00000001); - const uint32_t f_s_mask = uint32_li(0x80000000); - const uint32_t f_e_mask = uint32_li(0x7f800000); - const uint32_t f_m_mask = uint32_li(0x007fffff); - const uint32_t f_m_hidden_bit = uint32_li(0x00800000); - const uint32_t f_m_round_bit = uint32_li(0x00001000); - const uint32_t f_snan_mask = uint32_li(0x7fc00000); - const uint32_t f_e_pos = uint32_li(0x00000017); - const uint32_t h_e_pos = uint32_li(0x0000000a); - const uint32_t h_e_mask = uint32_li(0x00007c00); - const uint32_t h_snan_mask = uint32_li(0x00007e00); - const uint32_t h_e_mask_value = uint32_li(0x0000001f); - const uint32_t f_h_s_pos_offset = uint32_li(0x00000010); - const uint32_t f_h_bias_offset = uint32_li(0x00000070); - const uint32_t f_h_m_pos_offset = uint32_li(0x0000000d); - const uint32_t h_nan_min = uint32_li(0x00007c01); - const uint32_t f_h_e_biased_flag = uint32_li(0x0000008f); - const uint32_t f_s = uint32_and(ftou.ui, f_s_mask); - const uint32_t f_e = uint32_and(ftou.ui, f_e_mask); - const uint16_t h_s = (uint16_t)uint32_srl(f_s, f_h_s_pos_offset); - const uint32_t f_m = uint32_and(ftou.ui, f_m_mask); - const uint16_t f_e_amount = (uint16_t)uint32_srl(f_e, f_e_pos); - const uint32_t f_e_half_bias = uint32_sub(f_e_amount, f_h_bias_offset); - const uint32_t f_snan = uint32_and(ftou.ui, f_snan_mask); - const uint32_t f_m_round_mask = uint32_and(f_m, f_m_round_bit); - const uint32_t f_m_round_offset = uint32_sll(f_m_round_mask, one); - const uint32_t f_m_rounded = uint32_add(f_m, f_m_round_offset); - const uint32_t f_m_denorm_sa = uint32_sub(one, f_e_half_bias); - const uint32_t f_m_with_hidden = uint32_or(f_m_rounded, f_m_hidden_bit); - const uint32_t f_m_denorm = uint32_srl(f_m_with_hidden, f_m_denorm_sa); - const uint32_t h_m_denorm = uint32_srl(f_m_denorm, f_h_m_pos_offset); - const uint32_t f_m_rounded_overflow = uint32_and(f_m_rounded, f_m_hidden_bit); - const uint32_t m_nan = uint32_srl(f_m, f_h_m_pos_offset); - const uint32_t h_em_nan = uint32_or(h_e_mask, m_nan); - const uint32_t h_e_norm_overflow_offset = uint32_inc(f_e_half_bias); - const uint32_t h_e_norm_overflow = uint32_sll(h_e_norm_overflow_offset, h_e_pos); - const uint32_t h_e_norm = uint32_sll(f_e_half_bias, h_e_pos); - const uint32_t h_m_norm = uint32_srl(f_m_rounded, f_h_m_pos_offset); - const uint32_t h_em_norm = uint32_or(h_e_norm, h_m_norm); - const uint32_t is_h_ndenorm_msb = uint32_sub(f_h_bias_offset, f_e_amount); - const uint32_t is_f_e_flagged_msb = uint32_sub(f_h_e_biased_flag, f_e_half_bias); - const uint32_t is_h_denorm_msb = uint32_not(is_h_ndenorm_msb); - const uint32_t is_f_m_eqz_msb = uint32_dec(f_m); - const uint32_t is_h_nan_eqz_msb = uint32_dec(m_nan); - const uint32_t is_f_inf_msb = uint32_and(is_f_e_flagged_msb, is_f_m_eqz_msb); - const uint32_t is_f_nan_underflow_msb = uint32_and(is_f_e_flagged_msb, is_h_nan_eqz_msb); - const uint32_t is_e_overflow_msb = uint32_sub(h_e_mask_value, f_e_half_bias); - const uint32_t is_h_inf_msb = uint32_or(is_e_overflow_msb, is_f_inf_msb); - const uint32_t is_f_nsnan_msb = uint32_sub(f_snan, f_snan_mask); - const uint32_t is_m_norm_overflow_msb = uint32_neg(f_m_rounded_overflow); - const uint32_t is_f_snan_msb = uint32_not(is_f_nsnan_msb); - const uint32_t h_em_overflow_result = uint32_sels(is_m_norm_overflow_msb, h_e_norm_overflow, h_em_norm); - const uint32_t h_em_nan_result = uint32_sels(is_f_e_flagged_msb, h_em_nan, h_em_overflow_result); - const uint32_t h_em_nan_underflow_result = uint32_sels(is_f_nan_underflow_msb, h_nan_min, h_em_nan_result); - const uint32_t h_em_inf_result = uint32_sels(is_h_inf_msb, h_e_mask, h_em_nan_underflow_result); - const uint32_t h_em_denorm_result = uint32_sels(is_h_denorm_msb, h_m_denorm, h_em_inf_result); - const uint32_t h_em_snan_result = uint32_sels(is_f_snan_msb, h_snan_mask, h_em_denorm_result); - const uint32_t h_result = uint32_or(h_s, h_em_snan_result); - - return (uint16_t)(h_result); - } - - inline float halfToFloat(uint16_t _a) - { - const uint32_t h_e_mask = uint32_li(0x00007c00); - const uint32_t h_m_mask = uint32_li(0x000003ff); - const uint32_t h_s_mask = uint32_li(0x00008000); - const uint32_t h_f_s_pos_offset = uint32_li(0x00000010); - const uint32_t h_f_e_pos_offset = uint32_li(0x0000000d); - const uint32_t h_f_bias_offset = uint32_li(0x0001c000); - const uint32_t f_e_mask = uint32_li(0x7f800000); - const uint32_t f_m_mask = uint32_li(0x007fffff); - const uint32_t h_f_e_denorm_bias = uint32_li(0x0000007e); - const uint32_t h_f_m_denorm_sa_bias = uint32_li(0x00000008); - const uint32_t f_e_pos = uint32_li(0x00000017); - const uint32_t h_e_mask_minus_one = uint32_li(0x00007bff); - const uint32_t h_e = uint32_and(_a, h_e_mask); - const uint32_t h_m = uint32_and(_a, h_m_mask); - const uint32_t h_s = uint32_and(_a, h_s_mask); - const uint32_t h_e_f_bias = uint32_add(h_e, h_f_bias_offset); - const uint32_t h_m_nlz = uint32_cntlz(h_m); - const uint32_t f_s = uint32_sll(h_s, h_f_s_pos_offset); - const uint32_t f_e = uint32_sll(h_e_f_bias, h_f_e_pos_offset); - const uint32_t f_m = uint32_sll(h_m, h_f_e_pos_offset); - const uint32_t f_em = uint32_or(f_e, f_m); - const uint32_t h_f_m_sa = uint32_sub(h_m_nlz, h_f_m_denorm_sa_bias); - const uint32_t f_e_denorm_unpacked = uint32_sub(h_f_e_denorm_bias, h_f_m_sa); - const uint32_t h_f_m = uint32_sll(h_m, h_f_m_sa); - const uint32_t f_m_denorm = uint32_and(h_f_m, f_m_mask); - const uint32_t f_e_denorm = uint32_sll(f_e_denorm_unpacked, f_e_pos); - const uint32_t f_em_denorm = uint32_or(f_e_denorm, f_m_denorm); - const uint32_t f_em_nan = uint32_or(f_e_mask, f_m); - const uint32_t is_e_eqz_msb = uint32_dec(h_e); - const uint32_t is_m_nez_msb = uint32_neg(h_m); - const uint32_t is_e_flagged_msb = uint32_sub(h_e_mask_minus_one, h_e); - const uint32_t is_zero_msb = uint32_andc(is_e_eqz_msb, is_m_nez_msb); - const uint32_t is_inf_msb = uint32_andc(is_e_flagged_msb, is_m_nez_msb); - const uint32_t is_denorm_msb = uint32_and(is_m_nez_msb, is_e_eqz_msb); - const uint32_t is_nan_msb = uint32_and(is_e_flagged_msb, is_m_nez_msb); - const uint32_t is_zero = uint32_ext(is_zero_msb); - const uint32_t f_zero_result = uint32_andc(f_em, is_zero); - const uint32_t f_denorm_result = uint32_sels(is_denorm_msb, f_em_denorm, f_zero_result); - const uint32_t f_inf_result = uint32_sels(is_inf_msb, f_e_mask, f_denorm_result); - const uint32_t f_nan_result = uint32_sels(is_nan_msb, f_em_nan, f_inf_result); - const uint32_t f_result = uint32_or(f_s, f_nan_result); - - union { uint32_t ui; float flt; } utof; - utof.ui = f_result; - return utof.flt; - } - - inline uint16_t uint16_min(uint16_t _a, uint16_t _b) - { - return _a > _b ? _b : _a; - } - - inline uint16_t uint16_max(uint16_t _a, uint16_t _b) - { - return _a < _b ? _b : _a; - } - - inline int64_t int64_min(int64_t _a, int64_t _b) - { - return _a < _b ? _a : _b; - } - - inline int64_t int64_max(int64_t _a, int64_t _b) - { - return _a > _b ? _a : _b; - } - - inline int64_t int64_clamp(int64_t _a, int64_t _min, int64_t _max) - { - const int64_t min = int64_min(_a, _max); - const int64_t result = int64_max(_min, min); - - return result; - } - - inline uint64_t uint64_cntbits_ref(uint64_t _val) - { - const uint32_t lo = uint32_t(_val&UINT32_MAX); - const uint32_t hi = uint32_t(_val>>32); - - const uint32_t total = bx::uint32_cntbits(lo) - + bx::uint32_cntbits(hi); - - return total; - } + /// + uint16_t uint16_min(uint16_t _a, uint16_t _b); + + /// + uint16_t uint16_max(uint16_t _a, uint16_t _b); + + /// + int64_t int64_min(int64_t _a, int64_t _b); + + /// + int64_t int64_max(int64_t _a, int64_t _b); + + /// + int64_t int64_clamp(int64_t _a, int64_t _min, int64_t _max); + + /// + uint32_t uint64_cntbits_ref(uint64_t _val); /// Count number of bits set. - inline uint64_t uint64_cntbits(uint64_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_popcountll(_val); -#elif BX_COMPILER_MSVC && BX_ARCH_64BIT - return __popcnt64(_val); -#else - return uint64_cntbits_ref(_val); -#endif // BX_COMPILER_ - } - - inline uint64_t uint64_cntlz_ref(uint64_t _val) - { - return _val & UINT64_C(0xffffffff00000000) - ? uint32_cntlz(uint32_t(_val>>32) ) - : uint32_cntlz(uint32_t(_val) ) + 32 - ; - } + /// + uint32_t uint64_cntbits(uint64_t _val); + + /// + uint32_t uint64_cntlz_ref(uint64_t _val); /// Count number of leading zeros. - inline uint64_t uint64_cntlz(uint64_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_clzll(_val); -#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS && BX_ARCH_64BIT - unsigned long index; - _BitScanReverse64(&index, _val); - return 63 - index; -#else - return uint64_cntlz_ref(_val); -#endif // BX_COMPILER_ - } - - inline uint64_t uint64_cnttz_ref(uint64_t _val) - { - return _val & UINT64_C(0xffffffff) - ? uint32_cnttz(uint32_t(_val) ) - : uint32_cnttz(uint32_t(_val>>32) ) + 32 - ; - } - - inline uint64_t uint64_cnttz(uint64_t _val) - { -#if BX_COMPILER_GCC || BX_COMPILER_CLANG - return __builtin_ctzll(_val); -#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS && BX_ARCH_64BIT - unsigned long index; - _BitScanForward64(&index, _val); - return index; -#else - return uint64_cnttz_ref(_val); -#endif // BX_COMPILER_ - } - - inline uint64_t uint64_sll(uint64_t _a, int _sa) - { - return _a << _sa; - } - - inline uint64_t uint64_srl(uint64_t _a, int _sa) - { - return _a >> _sa; - } - - inline uint64_t uint64_sra(uint64_t _a, int _sa) - { - return ( (int64_t)_a) >> _sa; - } - - inline uint64_t uint64_rol(uint64_t _a, int _sa) - { - return ( _a << _sa) | (_a >> (32-_sa) ); - } - - inline uint64_t uint64_ror(uint64_t _a, int _sa) - { - return ( _a >> _sa) | (_a << (32-_sa) ); - } - - inline uint64_t uint64_add(uint64_t _a, uint64_t _b) - { - return _a + _b; - } - - inline uint64_t uint64_sub(uint64_t _a, uint64_t _b) - { - return _a - _b; - } - - inline uint64_t uint64_mul(uint64_t _a, uint64_t _b) - { - return _a * _b; - } + /// + uint32_t uint64_cntlz(uint64_t _val); + + /// + uint32_t uint64_cnttz_ref(uint64_t _val); + + /// + uint32_t uint64_cnttz(uint64_t _val); + + /// + uint64_t uint64_sll(uint64_t _a, int _sa); + + /// + uint64_t uint64_srl(uint64_t _a, int _sa); + + /// + uint64_t uint64_sra(uint64_t _a, int _sa); + + /// + uint64_t uint64_rol(uint64_t _a, int _sa); + + /// + uint64_t uint64_ror(uint64_t _a, int _sa); + + /// + uint64_t uint64_add(uint64_t _a, uint64_t _b); + + /// + uint64_t uint64_sub(uint64_t _a, uint64_t _b); + + /// + uint64_t uint64_mul(uint64_t _a, uint64_t _b); /// Greatest common divisor. - inline uint32_t uint32_gcd(uint32_t _a, uint32_t _b) - { - do - { - uint32_t tmp = _a % _b; - _a = _b; - _b = tmp; - } - while (_b); - - return _a; - } + /// + uint32_t uint32_gcd(uint32_t _a, uint32_t _b); /// Least common multiple. - inline uint32_t uint32_lcm(uint32_t _a, uint32_t _b) - { - return _a * (_b / uint32_gcd(_a, _b) ); - } + /// + uint32_t uint32_lcm(uint32_t _a, uint32_t _b); /// Align to arbitrary stride. - inline uint32_t strideAlign(uint32_t _offset, uint32_t _stride) - { - const uint32_t mod = uint32_mod(_offset, _stride); - const uint32_t add = uint32_sub(_stride, mod); - const uint32_t mask = uint32_cmpeq(mod, 0); - const uint32_t tmp = uint32_selb(mask, 0, add); - const uint32_t result = uint32_add(_offset, tmp); - - return result; - } + /// + uint32_t strideAlign(uint32_t _offset, uint32_t _stride); /// Align to arbitrary stride and 16-bytes. - inline uint32_t strideAlign16(uint32_t _offset, uint32_t _stride) - { - const uint32_t align = uint32_lcm(16, _stride); - const uint32_t mod = uint32_mod(_offset, align); - const uint32_t mask = uint32_cmpeq(mod, 0); - const uint32_t tmp0 = uint32_selb(mask, 0, align); - const uint32_t tmp1 = uint32_add(_offset, tmp0); - const uint32_t result = uint32_sub(tmp1, mod); - - return result; - } + /// + uint32_t strideAlign16(uint32_t _offset, uint32_t _stride); /// Align to arbitrary stride and 256-bytes. - inline uint32_t strideAlign256(uint32_t _offset, uint32_t _stride) - { - const uint32_t align = uint32_lcm(256, _stride); - const uint32_t mod = uint32_mod(_offset, align); - const uint32_t mask = uint32_cmpeq(mod, 0); - const uint32_t tmp0 = uint32_selb(mask, 0, align); - const uint32_t tmp1 = uint32_add(_offset, tmp0); - const uint32_t result = uint32_sub(tmp1, mod); - - return result; - } + /// + uint32_t strideAlign256(uint32_t _offset, uint32_t _stride); } // namespace bx +#include "uint32_t.inl" + #endif // BX_UINT32_T_H_HEADER_GUARD diff --git a/3rdparty/bx/include/bx/uint32_t.inl b/3rdparty/bx/include/bx/uint32_t.inl new file mode 100644 index 00000000000..8a66a07ca2d --- /dev/null +++ b/3rdparty/bx/include/bx/uint32_t.inl @@ -0,0 +1,781 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +// Copyright 2006 Mike Acton <macton@gmail.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE + +#ifndef BX_UINT32_T_H_HEADER_GUARD +# error "Must be included from bx/uint32_t.h" +#endif // BX_UINT32_T_H_HEADER_GUARD + +namespace bx +{ + inline uint32_t uint32_li(uint32_t _a) + { + return _a; + } + + inline uint32_t uint32_dec(uint32_t _a) + { + return _a - 1; + } + + inline uint32_t uint32_inc(uint32_t _a) + { + return _a + 1; + } + + inline uint32_t uint32_not(uint32_t _a) + { + return ~_a; + } + + inline uint32_t uint32_neg(uint32_t _a) + { + return -(int32_t)_a; + } + + inline uint32_t uint32_ext(uint32_t _a) + { + return ( (int32_t)_a)>>31; + } + + inline uint32_t uint32_and(uint32_t _a, uint32_t _b) + { + return _a & _b; + } + + inline uint32_t uint32_andc(uint32_t _a, uint32_t _b) + { + return _a & ~_b; + } + + inline uint32_t uint32_xor(uint32_t _a, uint32_t _b) + { + return _a ^ _b; + } + + inline uint32_t uint32_xorl(uint32_t _a, uint32_t _b) + { + return !_a != !_b; + } + + inline uint32_t uint32_or(uint32_t _a, uint32_t _b) + { + return _a | _b; + } + + inline uint32_t uint32_orc(uint32_t _a, uint32_t _b) + { + return _a | ~_b; + } + + inline uint32_t uint32_sll(uint32_t _a, int _sa) + { + return _a << _sa; + } + + inline uint32_t uint32_srl(uint32_t _a, int _sa) + { + return _a >> _sa; + } + + inline uint32_t uint32_sra(uint32_t _a, int _sa) + { + return ( (int32_t)_a) >> _sa; + } + + inline uint32_t uint32_rol(uint32_t _a, int _sa) + { + return ( _a << _sa) | (_a >> (32-_sa) ); + } + + inline uint32_t uint32_ror(uint32_t _a, int _sa) + { + return ( _a >> _sa) | (_a << (32-_sa) ); + } + + inline uint32_t uint32_add(uint32_t _a, uint32_t _b) + { + return _a + _b; + } + + inline uint32_t uint32_sub(uint32_t _a, uint32_t _b) + { + return _a - _b; + } + + inline uint32_t uint32_mul(uint32_t _a, uint32_t _b) + { + return _a * _b; + } + + inline uint32_t uint32_div(uint32_t _a, uint32_t _b) + { + return (_a / _b); + } + + inline uint32_t uint32_mod(uint32_t _a, uint32_t _b) + { + return (_a % _b); + } + + inline uint32_t uint32_cmpeq(uint32_t _a, uint32_t _b) + { + return -(_a == _b); + } + + inline uint32_t uint32_cmpneq(uint32_t _a, uint32_t _b) + { + return -(_a != _b); + } + + inline uint32_t uint32_cmplt(uint32_t _a, uint32_t _b) + { + return -(_a < _b); + } + + inline uint32_t uint32_cmple(uint32_t _a, uint32_t _b) + { + return -(_a <= _b); + } + + inline uint32_t uint32_cmpgt(uint32_t _a, uint32_t _b) + { + return -(_a > _b); + } + + inline uint32_t uint32_cmpge(uint32_t _a, uint32_t _b) + { + return -(_a >= _b); + } + + inline uint32_t uint32_setnz(uint32_t _a) + { + return -!!_a; + } + + inline uint32_t uint32_satadd(uint32_t _a, uint32_t _b) + { + const uint32_t add = uint32_add(_a, _b); + const uint32_t lt = uint32_cmplt(add, _a); + const uint32_t result = uint32_or(add, lt); + + return result; + } + + inline uint32_t uint32_satsub(uint32_t _a, uint32_t _b) + { + const uint32_t sub = uint32_sub(_a, _b); + const uint32_t le = uint32_cmple(sub, _a); + const uint32_t result = uint32_and(sub, le); + + return result; + } + + inline uint32_t uint32_satmul(uint32_t _a, uint32_t _b) + { + const uint64_t mul = (uint64_t)_a * (uint64_t)_b; + const uint32_t hi = mul >> 32; + const uint32_t nz = uint32_setnz(hi); + const uint32_t result = uint32_or(uint32_t(mul), nz); + + return result; + } + + inline uint32_t uint32_sels(uint32_t test, uint32_t _a, uint32_t _b) + { + const uint32_t mask = uint32_ext(test); + const uint32_t sel_a = uint32_and(_a, mask); + const uint32_t sel_b = uint32_andc(_b, mask); + const uint32_t result = uint32_or(sel_a, sel_b); + + return (result); + } + + inline uint32_t uint32_selb(uint32_t _mask, uint32_t _a, uint32_t _b) + { + const uint32_t sel_a = uint32_and(_a, _mask); + const uint32_t sel_b = uint32_andc(_b, _mask); + const uint32_t result = uint32_or(sel_a, sel_b); + + return (result); + } + + inline uint32_t uint32_imin(uint32_t _a, uint32_t _b) + { + const uint32_t a_sub_b = uint32_sub(_a, _b); + const uint32_t result = uint32_sels(a_sub_b, _a, _b); + + return result; + } + + inline uint32_t uint32_imax(uint32_t _a, uint32_t _b) + { + const uint32_t b_sub_a = uint32_sub(_b, _a); + const uint32_t result = uint32_sels(b_sub_a, _a, _b); + + return result; + } + + inline uint32_t uint32_min(uint32_t _a, uint32_t _b) + { + return _a > _b ? _b : _a; + } + + inline uint32_t uint32_min(uint32_t _a, uint32_t _b, uint32_t _c) + { + return uint32_min(_a, uint32_min(_b, _c) ); + } + + inline uint32_t uint32_max(uint32_t _a, uint32_t _b) + { + return _a > _b ? _a : _b; + } + + inline uint32_t uint32_max(uint32_t _a, uint32_t _b, uint32_t _c) + { + return uint32_max(_a, uint32_max(_b, _c) ); + } + + inline uint32_t uint32_clamp(uint32_t _a, uint32_t _min, uint32_t _max) + { + const uint32_t tmp = uint32_max(_a, _min); + const uint32_t result = uint32_min(tmp, _max); + + return result; + } + + inline uint32_t uint32_iclamp(uint32_t _a, uint32_t _min, uint32_t _max) + { + const uint32_t tmp = uint32_imax(_a, _min); + const uint32_t result = uint32_imin(tmp, _max); + + return result; + } + + inline uint32_t uint32_incwrap(uint32_t _val, uint32_t _min, uint32_t _max) + { + const uint32_t inc = uint32_inc(_val); + const uint32_t max_diff = uint32_sub(_max, _val); + const uint32_t neg_max_diff = uint32_neg(max_diff); + const uint32_t max_or = uint32_or(max_diff, neg_max_diff); + const uint32_t max_diff_nz = uint32_ext(max_or); + const uint32_t result = uint32_selb(max_diff_nz, inc, _min); + + return result; + } + + inline uint32_t uint32_decwrap(uint32_t _val, uint32_t _min, uint32_t _max) + { + const uint32_t dec = uint32_dec(_val); + const uint32_t min_diff = uint32_sub(_min, _val); + const uint32_t neg_min_diff = uint32_neg(min_diff); + const uint32_t min_or = uint32_or(min_diff, neg_min_diff); + const uint32_t min_diff_nz = uint32_ext(min_or); + const uint32_t result = uint32_selb(min_diff_nz, dec, _max); + + return result; + } + + inline uint32_t uint32_cntbits_ref(uint32_t _val) + { + const uint32_t tmp0 = uint32_srl(_val, 1); + const uint32_t tmp1 = uint32_and(tmp0, 0x55555555); + const uint32_t tmp2 = uint32_sub(_val, tmp1); + const uint32_t tmp3 = uint32_and(tmp2, 0xc30c30c3); + const uint32_t tmp4 = uint32_srl(tmp2, 2); + const uint32_t tmp5 = uint32_and(tmp4, 0xc30c30c3); + const uint32_t tmp6 = uint32_srl(tmp2, 4); + const uint32_t tmp7 = uint32_and(tmp6, 0xc30c30c3); + const uint32_t tmp8 = uint32_add(tmp3, tmp5); + const uint32_t tmp9 = uint32_add(tmp7, tmp8); + const uint32_t tmpA = uint32_srl(tmp9, 6); + const uint32_t tmpB = uint32_add(tmp9, tmpA); + const uint32_t tmpC = uint32_srl(tmpB, 12); + const uint32_t tmpD = uint32_srl(tmpB, 24); + const uint32_t tmpE = uint32_add(tmpB, tmpC); + const uint32_t tmpF = uint32_add(tmpD, tmpE); + const uint32_t result = uint32_and(tmpF, 0x3f); + + return result; + } + + /// Count number of bits set. + inline uint32_t uint32_cntbits(uint32_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_popcount(_val); +#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS + return __popcnt(_val); +#else + return uint32_cntbits_ref(_val); +#endif // BX_COMPILER_ + } + + inline uint32_t uint32_cntlz_ref(uint32_t _val) + { + const uint32_t tmp0 = uint32_srl(_val, 1); + const uint32_t tmp1 = uint32_or(tmp0, _val); + const uint32_t tmp2 = uint32_srl(tmp1, 2); + const uint32_t tmp3 = uint32_or(tmp2, tmp1); + const uint32_t tmp4 = uint32_srl(tmp3, 4); + const uint32_t tmp5 = uint32_or(tmp4, tmp3); + const uint32_t tmp6 = uint32_srl(tmp5, 8); + const uint32_t tmp7 = uint32_or(tmp6, tmp5); + const uint32_t tmp8 = uint32_srl(tmp7, 16); + const uint32_t tmp9 = uint32_or(tmp8, tmp7); + const uint32_t tmpA = uint32_not(tmp9); + const uint32_t result = uint32_cntbits(tmpA); + + return result; + } + + /// Count number of leading zeros. + inline uint32_t uint32_cntlz(uint32_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_clz(_val); +#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS + unsigned long index; + _BitScanReverse(&index, _val); + return 31 - index; +#else + return uint32_cntlz_ref(_val); +#endif // BX_COMPILER_ + } + + inline uint32_t uint32_cnttz_ref(uint32_t _val) + { + const uint32_t tmp0 = uint32_not(_val); + const uint32_t tmp1 = uint32_dec(_val); + const uint32_t tmp2 = uint32_and(tmp0, tmp1); + const uint32_t result = uint32_cntbits(tmp2); + + return result; + } + + inline uint32_t uint32_cnttz(uint32_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_ctz(_val); +#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS + unsigned long index; + _BitScanForward(&index, _val); + return index; +#else + return uint32_cnttz_ref(_val); +#endif // BX_COMPILER_ + } + + // shuffle: + // ---- ---- ---- ---- fedc ba98 7654 3210 + // to: + // -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 + inline uint32_t uint32_part1by1(uint32_t _a) + { + const uint32_t val = uint32_and(_a, 0xffff); + + const uint32_t tmp0 = uint32_sll(val, 8); + const uint32_t tmp1 = uint32_xor(val, tmp0); + const uint32_t tmp2 = uint32_and(tmp1, 0x00ff00ff); + + const uint32_t tmp3 = uint32_sll(tmp2, 4); + const uint32_t tmp4 = uint32_xor(tmp2, tmp3); + const uint32_t tmp5 = uint32_and(tmp4, 0x0f0f0f0f); + + const uint32_t tmp6 = uint32_sll(tmp5, 2); + const uint32_t tmp7 = uint32_xor(tmp5, tmp6); + const uint32_t tmp8 = uint32_and(tmp7, 0x33333333); + + const uint32_t tmp9 = uint32_sll(tmp8, 1); + const uint32_t tmpA = uint32_xor(tmp8, tmp9); + const uint32_t result = uint32_and(tmpA, 0x55555555); + + return result; + } + + // shuffle: + // ---- ---- ---- ---- ---- --98 7654 3210 + // to: + // ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 + inline uint32_t uint32_part1by2(uint32_t _a) + { + const uint32_t val = uint32_and(_a, 0x3ff); + + const uint32_t tmp0 = uint32_sll(val, 16); + const uint32_t tmp1 = uint32_xor(val, tmp0); + const uint32_t tmp2 = uint32_and(tmp1, 0xff0000ff); + + const uint32_t tmp3 = uint32_sll(tmp2, 8); + const uint32_t tmp4 = uint32_xor(tmp2, tmp3); + const uint32_t tmp5 = uint32_and(tmp4, 0x0300f00f); + + const uint32_t tmp6 = uint32_sll(tmp5, 4); + const uint32_t tmp7 = uint32_xor(tmp5, tmp6); + const uint32_t tmp8 = uint32_and(tmp7, 0x030c30c3); + + const uint32_t tmp9 = uint32_sll(tmp8, 2); + const uint32_t tmpA = uint32_xor(tmp8, tmp9); + const uint32_t result = uint32_and(tmpA, 0x09249249); + + return result; + } + + inline uint32_t uint32_testpow2(uint32_t _a) + { + const uint32_t tmp0 = uint32_not(_a); + const uint32_t tmp1 = uint32_inc(tmp0); + const uint32_t tmp2 = uint32_and(_a, tmp1); + const uint32_t tmp3 = uint32_cmpeq(tmp2, _a); + const uint32_t tmp4 = uint32_cmpneq(_a, 0); + const uint32_t result = uint32_and(tmp3, tmp4); + + return result; + } + + inline uint32_t uint32_nextpow2(uint32_t _a) + { + const uint32_t tmp0 = uint32_dec(_a); + const uint32_t tmp1 = uint32_srl(tmp0, 1); + const uint32_t tmp2 = uint32_or(tmp0, tmp1); + const uint32_t tmp3 = uint32_srl(tmp2, 2); + const uint32_t tmp4 = uint32_or(tmp2, tmp3); + const uint32_t tmp5 = uint32_srl(tmp4, 4); + const uint32_t tmp6 = uint32_or(tmp4, tmp5); + const uint32_t tmp7 = uint32_srl(tmp6, 8); + const uint32_t tmp8 = uint32_or(tmp6, tmp7); + const uint32_t tmp9 = uint32_srl(tmp8, 16); + const uint32_t tmpA = uint32_or(tmp8, tmp9); + const uint32_t result = uint32_inc(tmpA); + + return result; + } + + inline uint16_t halfFromFloat(float _a) + { + union { uint32_t ui; float flt; } ftou; + ftou.flt = _a; + + const uint32_t one = uint32_li(0x00000001); + const uint32_t f_s_mask = uint32_li(0x80000000); + const uint32_t f_e_mask = uint32_li(0x7f800000); + const uint32_t f_m_mask = uint32_li(0x007fffff); + const uint32_t f_m_hidden_bit = uint32_li(0x00800000); + const uint32_t f_m_round_bit = uint32_li(0x00001000); + const uint32_t f_snan_mask = uint32_li(0x7fc00000); + const uint32_t f_e_pos = uint32_li(0x00000017); + const uint32_t h_e_pos = uint32_li(0x0000000a); + const uint32_t h_e_mask = uint32_li(0x00007c00); + const uint32_t h_snan_mask = uint32_li(0x00007e00); + const uint32_t h_e_mask_value = uint32_li(0x0000001f); + const uint32_t f_h_s_pos_offset = uint32_li(0x00000010); + const uint32_t f_h_bias_offset = uint32_li(0x00000070); + const uint32_t f_h_m_pos_offset = uint32_li(0x0000000d); + const uint32_t h_nan_min = uint32_li(0x00007c01); + const uint32_t f_h_e_biased_flag = uint32_li(0x0000008f); + const uint32_t f_s = uint32_and(ftou.ui, f_s_mask); + const uint32_t f_e = uint32_and(ftou.ui, f_e_mask); + const uint16_t h_s = (uint16_t)uint32_srl(f_s, f_h_s_pos_offset); + const uint32_t f_m = uint32_and(ftou.ui, f_m_mask); + const uint16_t f_e_amount = (uint16_t)uint32_srl(f_e, f_e_pos); + const uint32_t f_e_half_bias = uint32_sub(f_e_amount, f_h_bias_offset); + const uint32_t f_snan = uint32_and(ftou.ui, f_snan_mask); + const uint32_t f_m_round_mask = uint32_and(f_m, f_m_round_bit); + const uint32_t f_m_round_offset = uint32_sll(f_m_round_mask, one); + const uint32_t f_m_rounded = uint32_add(f_m, f_m_round_offset); + const uint32_t f_m_denorm_sa = uint32_sub(one, f_e_half_bias); + const uint32_t f_m_with_hidden = uint32_or(f_m_rounded, f_m_hidden_bit); + const uint32_t f_m_denorm = uint32_srl(f_m_with_hidden, f_m_denorm_sa); + const uint32_t h_m_denorm = uint32_srl(f_m_denorm, f_h_m_pos_offset); + const uint32_t f_m_rounded_overflow = uint32_and(f_m_rounded, f_m_hidden_bit); + const uint32_t m_nan = uint32_srl(f_m, f_h_m_pos_offset); + const uint32_t h_em_nan = uint32_or(h_e_mask, m_nan); + const uint32_t h_e_norm_overflow_offset = uint32_inc(f_e_half_bias); + const uint32_t h_e_norm_overflow = uint32_sll(h_e_norm_overflow_offset, h_e_pos); + const uint32_t h_e_norm = uint32_sll(f_e_half_bias, h_e_pos); + const uint32_t h_m_norm = uint32_srl(f_m_rounded, f_h_m_pos_offset); + const uint32_t h_em_norm = uint32_or(h_e_norm, h_m_norm); + const uint32_t is_h_ndenorm_msb = uint32_sub(f_h_bias_offset, f_e_amount); + const uint32_t is_f_e_flagged_msb = uint32_sub(f_h_e_biased_flag, f_e_half_bias); + const uint32_t is_h_denorm_msb = uint32_not(is_h_ndenorm_msb); + const uint32_t is_f_m_eqz_msb = uint32_dec(f_m); + const uint32_t is_h_nan_eqz_msb = uint32_dec(m_nan); + const uint32_t is_f_inf_msb = uint32_and(is_f_e_flagged_msb, is_f_m_eqz_msb); + const uint32_t is_f_nan_underflow_msb = uint32_and(is_f_e_flagged_msb, is_h_nan_eqz_msb); + const uint32_t is_e_overflow_msb = uint32_sub(h_e_mask_value, f_e_half_bias); + const uint32_t is_h_inf_msb = uint32_or(is_e_overflow_msb, is_f_inf_msb); + const uint32_t is_f_nsnan_msb = uint32_sub(f_snan, f_snan_mask); + const uint32_t is_m_norm_overflow_msb = uint32_neg(f_m_rounded_overflow); + const uint32_t is_f_snan_msb = uint32_not(is_f_nsnan_msb); + const uint32_t h_em_overflow_result = uint32_sels(is_m_norm_overflow_msb, h_e_norm_overflow, h_em_norm); + const uint32_t h_em_nan_result = uint32_sels(is_f_e_flagged_msb, h_em_nan, h_em_overflow_result); + const uint32_t h_em_nan_underflow_result = uint32_sels(is_f_nan_underflow_msb, h_nan_min, h_em_nan_result); + const uint32_t h_em_inf_result = uint32_sels(is_h_inf_msb, h_e_mask, h_em_nan_underflow_result); + const uint32_t h_em_denorm_result = uint32_sels(is_h_denorm_msb, h_m_denorm, h_em_inf_result); + const uint32_t h_em_snan_result = uint32_sels(is_f_snan_msb, h_snan_mask, h_em_denorm_result); + const uint32_t h_result = uint32_or(h_s, h_em_snan_result); + + return (uint16_t)(h_result); + } + + inline float halfToFloat(uint16_t _a) + { + const uint32_t h_e_mask = uint32_li(0x00007c00); + const uint32_t h_m_mask = uint32_li(0x000003ff); + const uint32_t h_s_mask = uint32_li(0x00008000); + const uint32_t h_f_s_pos_offset = uint32_li(0x00000010); + const uint32_t h_f_e_pos_offset = uint32_li(0x0000000d); + const uint32_t h_f_bias_offset = uint32_li(0x0001c000); + const uint32_t f_e_mask = uint32_li(0x7f800000); + const uint32_t f_m_mask = uint32_li(0x007fffff); + const uint32_t h_f_e_denorm_bias = uint32_li(0x0000007e); + const uint32_t h_f_m_denorm_sa_bias = uint32_li(0x00000008); + const uint32_t f_e_pos = uint32_li(0x00000017); + const uint32_t h_e_mask_minus_one = uint32_li(0x00007bff); + const uint32_t h_e = uint32_and(_a, h_e_mask); + const uint32_t h_m = uint32_and(_a, h_m_mask); + const uint32_t h_s = uint32_and(_a, h_s_mask); + const uint32_t h_e_f_bias = uint32_add(h_e, h_f_bias_offset); + const uint32_t h_m_nlz = uint32_cntlz(h_m); + const uint32_t f_s = uint32_sll(h_s, h_f_s_pos_offset); + const uint32_t f_e = uint32_sll(h_e_f_bias, h_f_e_pos_offset); + const uint32_t f_m = uint32_sll(h_m, h_f_e_pos_offset); + const uint32_t f_em = uint32_or(f_e, f_m); + const uint32_t h_f_m_sa = uint32_sub(h_m_nlz, h_f_m_denorm_sa_bias); + const uint32_t f_e_denorm_unpacked = uint32_sub(h_f_e_denorm_bias, h_f_m_sa); + const uint32_t h_f_m = uint32_sll(h_m, h_f_m_sa); + const uint32_t f_m_denorm = uint32_and(h_f_m, f_m_mask); + const uint32_t f_e_denorm = uint32_sll(f_e_denorm_unpacked, f_e_pos); + const uint32_t f_em_denorm = uint32_or(f_e_denorm, f_m_denorm); + const uint32_t f_em_nan = uint32_or(f_e_mask, f_m); + const uint32_t is_e_eqz_msb = uint32_dec(h_e); + const uint32_t is_m_nez_msb = uint32_neg(h_m); + const uint32_t is_e_flagged_msb = uint32_sub(h_e_mask_minus_one, h_e); + const uint32_t is_zero_msb = uint32_andc(is_e_eqz_msb, is_m_nez_msb); + const uint32_t is_inf_msb = uint32_andc(is_e_flagged_msb, is_m_nez_msb); + const uint32_t is_denorm_msb = uint32_and(is_m_nez_msb, is_e_eqz_msb); + const uint32_t is_nan_msb = uint32_and(is_e_flagged_msb, is_m_nez_msb); + const uint32_t is_zero = uint32_ext(is_zero_msb); + const uint32_t f_zero_result = uint32_andc(f_em, is_zero); + const uint32_t f_denorm_result = uint32_sels(is_denorm_msb, f_em_denorm, f_zero_result); + const uint32_t f_inf_result = uint32_sels(is_inf_msb, f_e_mask, f_denorm_result); + const uint32_t f_nan_result = uint32_sels(is_nan_msb, f_em_nan, f_inf_result); + const uint32_t f_result = uint32_or(f_s, f_nan_result); + + union { uint32_t ui; float flt; } utof; + utof.ui = f_result; + return utof.flt; + } + + inline uint16_t uint16_min(uint16_t _a, uint16_t _b) + { + return _a > _b ? _b : _a; + } + + inline uint16_t uint16_max(uint16_t _a, uint16_t _b) + { + return _a < _b ? _b : _a; + } + + inline int64_t int64_min(int64_t _a, int64_t _b) + { + return _a < _b ? _a : _b; + } + + inline int64_t int64_max(int64_t _a, int64_t _b) + { + return _a > _b ? _a : _b; + } + + inline int64_t int64_clamp(int64_t _a, int64_t _min, int64_t _max) + { + const int64_t min = int64_min(_a, _max); + const int64_t result = int64_max(_min, min); + + return result; + } + + inline uint32_t uint64_cntbits_ref(uint64_t _val) + { + const uint32_t lo = uint32_t(_val&UINT32_MAX); + const uint32_t hi = uint32_t(_val>>32); + + const uint32_t total = bx::uint32_cntbits(lo) + + bx::uint32_cntbits(hi); + return total; + } + + /// Count number of bits set. + inline uint32_t uint64_cntbits(uint64_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_popcountll(_val); +#elif BX_COMPILER_MSVC && BX_ARCH_64BIT + return uint32_t(__popcnt64(_val) ); +#else + return uint64_cntbits_ref(_val); +#endif // BX_COMPILER_ + } + + inline uint32_t uint64_cntlz_ref(uint64_t _val) + { + return _val & UINT64_C(0xffffffff00000000) + ? uint32_cntlz(uint32_t(_val>>32) ) + : uint32_cntlz(uint32_t(_val) ) + 32 + ; + } + + /// Count number of leading zeros. + inline uint32_t uint64_cntlz(uint64_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_clzll(_val); +#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS && BX_ARCH_64BIT + unsigned long index; + _BitScanReverse64(&index, _val); + return uint32_t(63 - index); +#else + return uint64_cntlz_ref(_val); +#endif // BX_COMPILER_ + } + + inline uint32_t uint64_cnttz_ref(uint64_t _val) + { + return _val & UINT64_C(0xffffffff) + ? uint32_cnttz(uint32_t(_val) ) + : uint32_cnttz(uint32_t(_val>>32) ) + 32 + ; + } + + inline uint32_t uint64_cnttz(uint64_t _val) + { +#if BX_COMPILER_GCC || BX_COMPILER_CLANG + return __builtin_ctzll(_val); +#elif BX_COMPILER_MSVC && BX_PLATFORM_WINDOWS && BX_ARCH_64BIT + unsigned long index; + _BitScanForward64(&index, _val); + return uint32_t(index); +#else + return uint64_cnttz_ref(_val); +#endif // BX_COMPILER_ + } + + inline uint64_t uint64_sll(uint64_t _a, int _sa) + { + return _a << _sa; + } + + inline uint64_t uint64_srl(uint64_t _a, int _sa) + { + return _a >> _sa; + } + + inline uint64_t uint64_sra(uint64_t _a, int _sa) + { + return ( (int64_t)_a) >> _sa; + } + + inline uint64_t uint64_rol(uint64_t _a, int _sa) + { + return ( _a << _sa) | (_a >> (32-_sa) ); + } + + inline uint64_t uint64_ror(uint64_t _a, int _sa) + { + return ( _a >> _sa) | (_a << (32-_sa) ); + } + + inline uint64_t uint64_add(uint64_t _a, uint64_t _b) + { + return _a + _b; + } + + inline uint64_t uint64_sub(uint64_t _a, uint64_t _b) + { + return _a - _b; + } + + inline uint64_t uint64_mul(uint64_t _a, uint64_t _b) + { + return _a * _b; + } + + /// Greatest common divisor. + inline uint32_t uint32_gcd(uint32_t _a, uint32_t _b) + { + do + { + uint32_t tmp = _a % _b; + _a = _b; + _b = tmp; + } + while (_b); + + return _a; + } + + /// Least common multiple. + inline uint32_t uint32_lcm(uint32_t _a, uint32_t _b) + { + return _a * (_b / uint32_gcd(_a, _b) ); + } + + /// Align to arbitrary stride. + inline uint32_t strideAlign(uint32_t _offset, uint32_t _stride) + { + const uint32_t mod = uint32_mod(_offset, _stride); + const uint32_t add = uint32_sub(_stride, mod); + const uint32_t mask = uint32_cmpeq(mod, 0); + const uint32_t tmp = uint32_selb(mask, 0, add); + const uint32_t result = uint32_add(_offset, tmp); + + return result; + } + + /// Align to arbitrary stride and 16-bytes. + inline uint32_t strideAlign16(uint32_t _offset, uint32_t _stride) + { + const uint32_t align = uint32_lcm(16, _stride); + const uint32_t mod = uint32_mod(_offset, align); + const uint32_t mask = uint32_cmpeq(mod, 0); + const uint32_t tmp0 = uint32_selb(mask, 0, align); + const uint32_t tmp1 = uint32_add(_offset, tmp0); + const uint32_t result = uint32_sub(tmp1, mod); + + return result; + } + + /// Align to arbitrary stride and 256-bytes. + inline uint32_t strideAlign256(uint32_t _offset, uint32_t _stride) + { + const uint32_t align = uint32_lcm(256, _stride); + const uint32_t mod = uint32_mod(_offset, align); + const uint32_t mask = uint32_cmpeq(mod, 0); + const uint32_t tmp0 = uint32_selb(mask, 0, align); + const uint32_t tmp1 = uint32_add(_offset, tmp0); + const uint32_t result = uint32_sub(tmp1, mod); + + return result; + } + +} // namespace bx diff --git a/3rdparty/bx/makefile b/3rdparty/bx/makefile index 6a6598f80b1..bf8d91167d2 100644 --- a/3rdparty/bx/makefile +++ b/3rdparty/bx/makefile @@ -1,6 +1,6 @@ # -# Copyright 2011-2015 Branimir Karadzic. All rights reserved. -# License: http://www.opensource.org/licenses/BSD-2-Clause +# Copyright 2011-2017 Branimir Karadzic. All rights reserved. +# License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause # GENIE=../bx/tools/bin/$(OS)/genie diff --git a/3rdparty/bx/scripts/bin2c.lua b/3rdparty/bx/scripts/bin2c.lua index 5dbc29d7b14..b308b3eb253 100644 --- a/3rdparty/bx/scripts/bin2c.lua +++ b/3rdparty/bx/scripts/bin2c.lua @@ -16,6 +16,10 @@ project "bin2c" "../tools/bin2c/**.h", } + links { + "bx", + } + configuration { "mingw-*" } targetextension ".exe" diff --git a/3rdparty/bx/scripts/bx.lua b/3rdparty/bx/scripts/bx.lua index 2f1e4e57585..b62ee4bae5f 100644 --- a/3rdparty/bx/scripts/bx.lua +++ b/3rdparty/bx/scripts/bx.lua @@ -2,24 +2,23 @@ -- Copyright 2010-2017 Branimir Karadzic. All rights reserved. -- License: https://github.com/bkaradzic/bx#license-bsd-2-clause -- - + project "bx" - uuid "4db0b09e-d6df-11e1-a0ec-65ccdd6a022f" kind "StaticLib" - configuration { "osx or ios" } - -- OSX ar doesn't like creating archive without object files - -- here is object file... - prebuildcommands { - "@echo \"void dummy() {}\" > /tmp/dummy.cpp", - } - files { - "/tmp/dummy.cpp", - } - - configuration {} + includedirs { + "../include", + } files { "../include/**.h", "../include/**.inl", + "../src/**.cpp", } + + configuration { "linux-*" } + buildoptions { + "-fPIC", + } + + configuration {} diff --git a/3rdparty/bx/scripts/genie.lua b/3rdparty/bx/scripts/genie.lua index 1e8f9028010..e0e634ae716 100644 --- a/3rdparty/bx/scripts/genie.lua +++ b/3rdparty/bx/scripts/genie.lua @@ -54,6 +54,10 @@ project "bx.test" path.join(BX_DIR, "tests/dbg.*"), } + links { + "bx", + } + configuration { "vs* or mingw*" } links { "psapi", @@ -109,6 +113,10 @@ project "bx.bench" path.join(BX_DIR, "tests/dbg.*"), } + links { + "bx", + } + configuration { "vs* or mingw*" } links { "psapi", diff --git a/3rdparty/bx/scripts/toolchain.lua b/3rdparty/bx/scripts/toolchain.lua index 5d8573a690e..6a01c92422c 100644 --- a/3rdparty/bx/scripts/toolchain.lua +++ b/3rdparty/bx/scripts/toolchain.lua @@ -532,21 +532,27 @@ function toolchain(_buildDir, _libDir) "__STDC_CONSTANT_MACROS", } - configuration { "qbs" } - flags { - "ExtraWarnings", - } - configuration { "Debug" } targetsuffix "Debug" + defines { + "_DEBUG", + } configuration { "Release" } flags { "NoBufferSecurityCheck", "OptimizeSpeed", } + defines { + "NDEBUG", + } targetsuffix "Release" + configuration { "qbs" } + flags { + "ExtraWarnings", + } + configuration { "vs*", "x32" } flags { "EnableSSE2", diff --git a/3rdparty/bx/src/commandline.cpp b/3rdparty/bx/src/commandline.cpp new file mode 100644 index 00000000000..400e4965a0e --- /dev/null +++ b/3rdparty/bx/src/commandline.cpp @@ -0,0 +1,322 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/commandline.h> +#include <bx/string.h> + +namespace bx +{ + // Reference: + // http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + const char* tokenizeCommandLine(const char* _commandLine, char* _buffer, uint32_t& _bufferSize, int32_t& _argc, char* _argv[], int32_t _maxArgvs, char _term) + { + int32_t argc = 0; + const char* curr = _commandLine; + char* currOut = _buffer; + char term = ' '; + bool sub = false; + + enum ParserState + { + SkipWhitespace, + SetTerm, + Copy, + Escape, + End, + }; + + ParserState state = SkipWhitespace; + + while ('\0' != *curr + && _term != *curr + && argc < _maxArgvs) + { + switch (state) + { + case SkipWhitespace: + for (; isSpace(*curr); ++curr) {}; // skip whitespace + state = SetTerm; + break; + + case SetTerm: + if ('"' == *curr) + { + term = '"'; + ++curr; // skip begining quote + } + else + { + term = ' '; + } + + _argv[argc] = currOut; + ++argc; + + state = Copy; + break; + + case Copy: + if ('\\' == *curr) + { + state = Escape; + } + else if ('"' == *curr + && '"' != term) + { + sub = !sub; + } + else if (isSpace(*curr) && !sub) + { + state = End; + } + else if (term != *curr || sub) + { + *currOut = *curr; + ++currOut; + } + else + { + state = End; + } + ++curr; + break; + + case Escape: + { + const char* start = --curr; + for (; '\\' == *curr; ++curr) {}; + + if ('"' != *curr) + { + int32_t count = (int32_t)(curr-start); + + curr = start; + for (int32_t ii = 0; ii < count; ++ii) + { + *currOut = *curr; + ++currOut; + ++curr; + } + } + else + { + curr = start+1; + *currOut = *curr; + ++currOut; + ++curr; + } + } + state = Copy; + break; + + case End: + *currOut = '\0'; + ++currOut; + state = SkipWhitespace; + break; + } + } + + *currOut = '\0'; + if (0 < argc + && '\0' == _argv[argc-1][0]) + { + --argc; + } + + _bufferSize = (uint32_t)(currOut - _buffer); + _argc = argc; + + if ('\0' != *curr) + { + ++curr; + } + + return curr; + } + + CommandLine::CommandLine(int32_t _argc, char const* const* _argv) + : m_argc(_argc) + , m_argv(_argv) + { + } + + const char* CommandLine::findOption(const char* _long, const char* _default) const + { + const char* result = find(0, '\0', _long, 1); + return result == NULL ? _default : result; + } + + const char* CommandLine::findOption(const char _short, const char* _long, const char* _default) const + { + const char* result = find(0, _short, _long, 1); + return result == NULL ? _default : result; + } + + const char* CommandLine::findOption(const char* _long, int32_t _numParams) const + { + const char* result = find(0, '\0', _long, _numParams); + return result; + } + + const char* CommandLine::findOption(const char _short, const char* _long, int32_t _numParams) const + { + const char* result = find(0, _short, _long, _numParams); + return result; + } + + const char* CommandLine::findOption(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const + { + const char* result = find(_skip, _short, _long, _numParams); + return result; + } + + bool CommandLine::hasArg(const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 0); + return NULL != arg; + } + + bool CommandLine::hasArg(const char* _long) const + { + const char* arg = findOption('\0', _long, 0); + return NULL != arg; + } + + bool CommandLine::hasArg(const char*& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + _value = arg; + return NULL != arg; + } + + bool CommandLine::hasArg(int32_t& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atoi(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(uint32_t& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atoi(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(float& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = float(atof(arg)); + return true; + } + + return false; + } + + bool CommandLine::hasArg(double& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + _value = atof(arg); + return true; + } + + return false; + } + + bool CommandLine::hasArg(bool& _value, const char _short, const char* _long) const + { + const char* arg = findOption(_short, _long, 1); + if (NULL != arg) + { + if ('0' == *arg || (0 == strincmp(arg, "false") ) ) + { + _value = false; + } + else if ('0' != *arg || (0 == strincmp(arg, "true") ) ) + { + _value = true; + } + + return true; + } + + return false; + } + + const char* CommandLine::find(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const + { + for (int32_t ii = 0; ii < m_argc; ++ii) + { + const char* arg = m_argv[ii]; + if ('-' == *arg) + { + ++arg; + if (_short == *arg) + { + if (1 == strnlen(arg) ) + { + if (0 == _skip) + { + if (0 == _numParams) + { + return ""; + } + else if (ii+_numParams < m_argc + && '-' != *m_argv[ii+1] ) + { + return m_argv[ii+1]; + } + + return NULL; + } + + --_skip; + ii += _numParams; + } + } + else if (NULL != _long + && '-' == *arg + && 0 == strincmp(arg+1, _long) ) + { + if (0 == _skip) + { + if (0 == _numParams) + { + return ""; + } + else if (ii+_numParams < m_argc + && '-' != *m_argv[ii+1] ) + { + return m_argv[ii+1]; + } + + return NULL; + } + + --_skip; + ii += _numParams; + } + } + } + + return NULL; + } + +} // namespace bx diff --git a/3rdparty/bx/src/crt.cpp b/3rdparty/bx/src/crt.cpp new file mode 100644 index 00000000000..8686f03d267 --- /dev/null +++ b/3rdparty/bx/src/crt.cpp @@ -0,0 +1,362 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/bx.h> +#include <bx/readerwriter.h> +#include <bx/debug.h> + +namespace bx +{ + void* memCopyRef(void* _dst, const void* _src, size_t _numBytes) + { + uint8_t* dst = (uint8_t*)_dst; + const uint8_t* end = dst + _numBytes; + const uint8_t* src = (const uint8_t*)_src; + while (dst != end) + { + *dst++ = *src++; + } + + return _dst; + } + + void* memCopy(void* _dst, const void* _src, size_t _numBytes) + { +#if BX_CRT_NONE + return memCopyRef(_dst, _src, _numBytes); +#else + return ::memcpy(_dst, _src, _numBytes); +#endif // BX_CRT_NONE + } + + void memCopy(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch, uint32_t _dstPitch) + { + const uint8_t* src = (const uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; + + for (uint32_t ii = 0; ii < _num; ++ii) + { + memCopy(dst, src, _size); + src += _srcPitch; + dst += _dstPitch; + } + } + + /// + void gather(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _srcPitch) + { + memCopy(_dst, _src, _size, _num, _srcPitch, _size); + } + + /// + void scatter(void* _dst, const void* _src, uint32_t _size, uint32_t _num, uint32_t _dstPitch) + { + memCopy(_dst, _src, _size, _num, _size, _dstPitch); + } + + void* memMoveRef(void* _dst, const void* _src, size_t _numBytes) + { + uint8_t* dst = (uint8_t*)_dst; + const uint8_t* src = (const uint8_t*)_src; + + if (_numBytes == 0 + || dst == src) + { + return dst; + } + + // if (src+_numBytes <= dst || end <= src) + if (dst < src) + { + return memcpy(_dst, _src, _numBytes); + } + + for (intptr_t ii = _numBytes-1; ii >= 0; --ii) + { + dst[ii] = src[ii]; + } + + return _dst; + } + + void* memMove(void* _dst, const void* _src, size_t _numBytes) + { +#if BX_CRT_NONE + return memMoveRef(_dst, _src, _numBytes); +#else + return ::memmove(_dst, _src, _numBytes); +#endif // BX_CRT_NONE + } + + void* memSetRef(void* _dst, uint8_t _ch, size_t _numBytes) + { + uint8_t* dst = (uint8_t*)_dst; + const uint8_t* end = dst + _numBytes; + while (dst != end) + { + *dst++ = char(_ch); + } + + return _dst; + } + + void* memSet(void* _dst, uint8_t _ch, size_t _numBytes) + { +#if BX_CRT_NONE + return memSetRef(_dst, _ch, _numBytes); +#else + return ::memset(_dst, _ch, _numBytes); +#endif // BX_CRT_NONE + } + + namespace + { + struct Param + { + int32_t width; + uint32_t base; + uint32_t prec; + char fill; + bool left; + }; + + static int32_t write(WriterI* _writer, const char* _str, int32_t _len, const Param& _param, Error* _err) + { + int32_t size = 0; + int32_t len = (int32_t)strnlen(_str, _len); + int32_t padding = _param.width > len ? _param.width - len : 0; + + if (!_param.left) + { + size += writeRep(_writer, _param.fill, padding, _err); + } + + size += write(_writer, _str, len, _err); + + if (_param.left) + { + size += writeRep(_writer, _param.fill, padding, _err); + } + + return size; + } + + static int32_t write(WriterI* _writer, const char* _str, const Param& _param, Error* _err) + { + return write(_writer, _str, INT32_MAX, _param, _err); + } + + static int32_t write(WriterI* _writer, int32_t _i, const Param& _param, Error* _err) + { + char str[33]; + int32_t len = toString(str, sizeof(str), _i, _param.base); + + if (len == 0) + { + return 0; + } + + return write(_writer, str, len, _param, _err); + } + + static int32_t write(WriterI* _writer, uint32_t _i, const Param& _param, Error* _err) + { + char str[33]; + int32_t len = toString(str, sizeof(str), _i, _param.base); + + if (len == 0) + { + return 0; + } + + return write(_writer, str, len, _param, _err); + } + + static int32_t write(WriterI* _writer, double _d, const Param& _param, Error* _err) + { + char str[1024]; + int32_t len = toString(str, sizeof(str), _d); + + if (len == 0) + { + return 0; + } + + const char* dot = strnchr(str, '.'); + const int32_t precLen = int32_t(dot + 1 + _param.prec - str); + if (precLen > len) + { + for (int32_t ii = len; ii < precLen; ++ii) + { + str[ii] = '0'; + } + str[precLen] = '\0'; + } + len = precLen; + + return write(_writer, str, len, _param, _err); + } + + static int32_t write(WriterI* _writer, const void* _ptr, const Param& _param, Error* _err) + { + char str[35] = "0x"; + int32_t len = toString(str + 2, sizeof(str) - 2, uint32_t(uintptr_t(_ptr) ), 16); + + if (len == 0) + { + return 0; + } + + len += 2; + return write(_writer, str, len, _param, _err); + } + } // anonymous namespace + + int32_t write(WriterI* _writer, const char* _format, va_list _argList, Error* _err) + { + MemoryReader reader(_format, strnlen(_format) ); + + int32_t size = 0; + + while (_err->isOk() ) + { + char ch = '\0'; + read(&reader, ch, _err); + + if (!_err->isOk() ) + { + break; + } + else if ('%' == ch) + { + // %[ -0][<width>][.<precision>] + read(&reader, ch); + + Param param; + param.base = 10; + param.prec = 6; + param.left = false; + param.fill = ' '; + param.width = 0; + + while (' ' == ch + || '-' == ch + || '0' == ch) + { + switch (ch) + { + case '-': param.left = true; break; + case ' ': param.fill = ' '; break; + case '0': param.fill = '0'; break; + } + + if (param.left) + { + param.fill = ' '; + } + + read(&reader, ch); + } + + if ('*' == ch) + { + read(&reader, ch); + param.width = va_arg(_argList, int32_t); + + if (0 > param.width) + { + param.left = true; + param.width = -param.width; + } + + } + else + { + while (isNumeric(ch) ) + { + param.width = param.width * 10 + ch - '0'; + read(&reader, ch); + } + } + + if ('.' == ch) + { + read(&reader, ch); + + if ('*' == ch) + { + read(&reader, ch); + param.prec = va_arg(_argList, int32_t); + } + else + { + param.prec = 0; + while (isNumeric(ch) ) + { + param.prec = param.prec * 10 + ch - '0'; + read(&reader, ch); + } + } + } + + switch (toLower(ch) ) + { + case 'c': + size += write(_writer, char(va_arg(_argList, int32_t) ), _err); + break; + + case 's': + size += write(_writer, va_arg(_argList, const char*), param, _err); + break; + + case 'd': + param.base = 10; + size += write(_writer, va_arg(_argList, int32_t), param, _err); + break; + + case 'f': + size += write(_writer, va_arg(_argList, double), param, _err); + break; + + case 'p': + size += write(_writer, va_arg(_argList, void*), param, _err); + break; + + case 'x': + param.base = 16; + size += write(_writer, va_arg(_argList, uint32_t), param, _err); + break; + + case 'u': + param.base = 10; + size += write(_writer, va_arg(_argList, uint32_t), param, _err); + break; + + default: + size += write(_writer, ch, _err); + break; + } + } + else + { + size += write(_writer, ch, _err); + } + } + + size += write(_writer, '\0', _err); + + return size; + } + + int32_t write(WriterI* _writer, Error* _err, const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + int32_t size = write(_writer, _format, argList, _err); + va_end(argList); + return size; + } + +} // namespace bx diff --git a/3rdparty/bx/src/crtimpl.cpp b/3rdparty/bx/src/crtimpl.cpp new file mode 100644 index 00000000000..7adb74bb8ee --- /dev/null +++ b/3rdparty/bx/src/crtimpl.cpp @@ -0,0 +1,360 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/crtimpl.h> + +#if BX_CONFIG_ALLOCATOR_CRT +# include <malloc.h> +#endif // BX_CONFIG_ALLOCATOR_CRT + +namespace bx +{ +#if BX_CONFIG_ALLOCATOR_CRT + CrtAllocator::CrtAllocator() + { + } + + CrtAllocator::~CrtAllocator() + { + } + + void* CrtAllocator::realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) + { + if (0 == _size) + { + if (NULL != _ptr) + { + if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) + { + ::free(_ptr); + return NULL; + } + +# if BX_COMPILER_MSVC + BX_UNUSED(_file, _line); + _aligned_free(_ptr); +# else + bx::alignedFree(this, _ptr, _align, _file, _line); +# endif // BX_ + } + + return NULL; + } + else if (NULL == _ptr) + { + if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) + { + return ::malloc(_size); + } + +# if BX_COMPILER_MSVC + BX_UNUSED(_file, _line); + return _aligned_malloc(_size, _align); +# else + return bx::alignedAlloc(this, _size, _align, _file, _line); +# endif // BX_ + } + + if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align) + { + return ::realloc(_ptr, _size); + } + +# if BX_COMPILER_MSVC + BX_UNUSED(_file, _line); + return _aligned_realloc(_ptr, _size, _align); +# else + return bx::alignedRealloc(this, _ptr, _size, _align, _file, _line); +# endif // BX_ + } +#endif // BX_CONFIG_ALLOCATOR_CRT + +#if BX_CONFIG_CRT_FILE_READER_WRITER + +# if BX_CRT_MSVC +# define fseeko64 _fseeki64 +# define ftello64 _ftelli64 +# elif 0 \ + || BX_PLATFORM_ANDROID \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_QNX +# define fseeko64 fseeko +# define ftello64 ftello +# elif BX_PLATFORM_PS4 +# define fseeko64 fseek +# define ftello64 ftell +# endif // BX_ + + CrtFileReader::CrtFileReader() + : m_file(NULL) + { + } + + CrtFileReader::~CrtFileReader() + { + } + + bool CrtFileReader::open(const char* _filePath, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + if (NULL != m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "CrtFileReader: File is already open."); + return false; + } + + m_file = fopen(_filePath, "rb"); + if (NULL == m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "CrtFileReader: Failed to open file."); + return false; + } + + return true; + } + + void CrtFileReader::close() + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + FILE* file = (FILE*)m_file; + fclose(file); + m_file = NULL; + } + + int64_t CrtFileReader::seek(int64_t _offset, Whence::Enum _whence) + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + FILE* file = (FILE*)m_file; + fseeko64(file, _offset, _whence); + return ftello64(file); + } + + int32_t CrtFileReader::read(void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + FILE* file = (FILE*)m_file; + int32_t size = (int32_t)fread(_data, 1, _size, file); + if (size != _size) + { + if (0 != feof(file) ) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "CrtFileReader: EOF."); + } + else if (0 != ferror(file) ) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "CrtFileReader: read error."); + } + + return size >= 0 ? size : 0; + } + + return size; + } + + CrtFileWriter::CrtFileWriter() + : m_file(NULL) + { + } + + CrtFileWriter::~CrtFileWriter() + { + } + + bool CrtFileWriter::open(const char* _filePath, bool _append, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + if (NULL != m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "CrtFileReader: File is already open."); + return false; + } + + m_file = fopen(_filePath, _append ? "ab" : "wb"); + + if (NULL == m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "CrtFileWriter: Failed to open file."); + return false; + } + + return true; + } + + void CrtFileWriter::close() + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + FILE* file = (FILE*)m_file; + fclose(file); + m_file = NULL; + } + + int64_t CrtFileWriter::seek(int64_t _offset, Whence::Enum _whence) + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + FILE* file = (FILE*)m_file; + fseeko64(file, _offset, _whence); + return ftello64(file); + } + + int32_t CrtFileWriter::write(const void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != m_file, "Reader/Writer file is not open."); + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + FILE* file = (FILE*)m_file; + int32_t size = (int32_t)fwrite(_data, 1, _size, file); + if (size != _size) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "CrtFileWriter: write failed."); + return size >= 0 ? size : 0; + } + + return size; + } +#endif // BX_CONFIG_CRT_FILE_READER_WRITER + +#if BX_CONFIG_CRT_PROCESS + +#if BX_CRT_MSVC +# define popen _popen +# define pclose _pclose +#endif // BX_CRT_MSVC + + ProcessReader::ProcessReader() + : m_file(NULL) + { + } + + ProcessReader::~ProcessReader() + { + BX_CHECK(NULL == m_file, "Process not closed!"); + } + + bool ProcessReader::open(const char* _command, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + if (NULL != m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessReader: File is already open."); + return false; + } + + m_file = popen(_command, "r"); + if (NULL == m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessReader: Failed to open process."); + return false; + } + + return true; + } + + void ProcessReader::close() + { + BX_CHECK(NULL != m_file, "Process not open!"); + FILE* file = (FILE*)m_file; + m_exitCode = pclose(file); + m_file = NULL; + } + + int32_t ProcessReader::read(void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + + FILE* file = (FILE*)m_file; + int32_t size = (int32_t)fread(_data, 1, _size, file); + if (size != _size) + { + if (0 != feof(file) ) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_EOF, "ProcessReader: EOF."); + } + else if (0 != ferror(file) ) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_READ, "ProcessReader: read error."); + } + + return size >= 0 ? size : 0; + } + + return size; + } + + int32_t ProcessReader::getExitCode() const + { + return m_exitCode; + } + + ProcessWriter::ProcessWriter() + : m_file(NULL) + { + } + + ProcessWriter::~ProcessWriter() + { + BX_CHECK(NULL == m_file, "Process not closed!"); + } + + bool ProcessWriter::open(const char* _command, bool, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); + + if (NULL != m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_ALREADY_OPEN, "ProcessWriter: File is already open."); + return false; + } + + m_file = popen(_command, "w"); + if (NULL == m_file) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_OPEN, "ProcessWriter: Failed to open process."); + return false; + } + + return true; + } + + void ProcessWriter::close() + { + BX_CHECK(NULL != m_file, "Process not open!"); + FILE* file = (FILE*)m_file; + m_exitCode = pclose(file); + m_file = NULL; + } + + int32_t ProcessWriter::write(const void* _data, int32_t _size, Error* _err) + { + BX_CHECK(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err); + + FILE* file = (FILE*)m_file; + int32_t size = (int32_t)fwrite(_data, 1, _size, file); + if (size != _size) + { + if (0 != ferror(file) ) + { + BX_ERROR_SET(_err, BX_ERROR_READERWRITER_WRITE, "ProcessWriter: write error."); + } + + return size >= 0 ? size : 0; + } + + return size; + } + + int32_t ProcessWriter::getExitCode() const + { + return m_exitCode; + } +#endif // BX_CONFIG_CRT_PROCESS + +} // namespace bx diff --git a/3rdparty/bx/src/debug.cpp b/3rdparty/bx/src/debug.cpp new file mode 100644 index 00000000000..550eef6e5f6 --- /dev/null +++ b/3rdparty/bx/src/debug.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/debug.h> +#include <bx/string.h> // isPrint +#include <inttypes.h> // PRIx* + +#if BX_PLATFORM_ANDROID +# include <android/log.h> +#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* _str); +#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX +# if defined(__OBJC__) +# import <Foundation/NSObjCRuntime.h> +# else +# include <CoreFoundation/CFString.h> +extern "C" void NSLog(CFStringRef _format, ...); +# endif // defined(__OBJC__) +#elif 0 // BX_PLATFORM_EMSCRIPTEN +# include <emscripten.h> +#else +# include <stdio.h> // fputs, fflush +#endif // BX_PLATFORM_WINDOWS + +namespace bx +{ + void debugBreak() + { +#if BX_COMPILER_MSVC + __debugbreak(); +#elif BX_CPU_ARM + __builtin_trap(); +// asm("bkpt 0"); +#elif !BX_PLATFORM_NACL && BX_CPU_X86 && (BX_COMPILER_GCC || BX_COMPILER_CLANG) + // NaCl doesn't like int 3: + // NativeClient: NaCl module load failed: Validation failure. File violates Native Client safety rules. + __asm__ ("int $3"); +#else // cross platform implementation + int* int3 = (int*)3L; + *int3 = 3; +#endif // BX + } + + void debugOutput(const char* _out) + { +#if BX_PLATFORM_ANDROID +# ifndef BX_ANDROID_LOG_TAG +# define BX_ANDROID_LOG_TAG "" +# endif // BX_ANDROID_LOG_TAG + __android_log_write(ANDROID_LOG_DEBUG, BX_ANDROID_LOG_TAG, _out); +#elif BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE + OutputDebugStringA(_out); +#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX +# if defined(__OBJC__) + NSLog(@"%s", _out); +# else + NSLog(__CFStringMakeConstantString("%s"), _out); +# endif // defined(__OBJC__) +#elif 0 // BX_PLATFORM_EMSCRIPTEN + emscripten_log(EM_LOG_CONSOLE, "%s", _out); +#else + fputs(_out, stdout); + fflush(stdout); +#endif // BX_PLATFORM_ + } + + void debugPrintfVargs(const char* _format, va_list _argList) + { + char temp[8192]; + char* out = temp; + int32_t len = vsnprintf(out, sizeof(temp), _format, _argList); + if ( (int32_t)sizeof(temp) < len) + { + out = (char*)alloca(len+1); + len = vsnprintf(out, len, _format, _argList); + } + out[len] = '\0'; + debugOutput(out); + } + + void debugPrintf(const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + debugPrintfVargs(_format, argList); + va_end(argList); + } + +#define DBG_ADDRESS "%" PRIxPTR + + void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...) + { +#define HEX_DUMP_WIDTH 16 +#define HEX_DUMP_SPACE_WIDTH 48 +#define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s" + + va_list argList; + va_start(argList, _format); + debugPrintfVargs(_format, argList); + va_end(argList); + + debugPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size); + + if (NULL != _data) + { + const uint8_t* data = reinterpret_cast<const uint8_t*>(_data); + char hex[HEX_DUMP_WIDTH*3+1]; + char ascii[HEX_DUMP_WIDTH+1]; + uint32_t hexPos = 0; + uint32_t asciiPos = 0; + for (uint32_t ii = 0; ii < _size; ++ii) + { + snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]); + hexPos += 3; + + ascii[asciiPos] = isPrint(data[asciiPos]) ? data[asciiPos] : '.'; + asciiPos++; + + if (HEX_DUMP_WIDTH == asciiPos) + { + ascii[asciiPos] = '\0'; + debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); + data += asciiPos; + hexPos = 0; + asciiPos = 0; + } + } + + if (0 != asciiPos) + { + ascii[asciiPos] = '\0'; + debugPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); + } + } + +#undef HEX_DUMP_WIDTH +#undef HEX_DUMP_SPACE_WIDTH +#undef HEX_DUMP_FORMAT + } + +} // namespace bx diff --git a/3rdparty/bx/src/dtoa.cpp b/3rdparty/bx/src/dtoa.cpp new file mode 100644 index 00000000000..05ac387fec2 --- /dev/null +++ b/3rdparty/bx/src/dtoa.cpp @@ -0,0 +1,528 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/cpu.h> +#include <bx/fpumath.h> +#include <bx/string.h> +#include <bx/uint32_t.h> + +namespace bx +{ + // https://github.com/miloyip/dtoa-benchmark + // + // Copyright (C) 2014 Milo Yip + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to deal + // in the Software without restriction, including without limitation the rights + // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + // copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + // THE SOFTWARE. + // + struct DiyFp + { + DiyFp() + { + } + + DiyFp(uint64_t _f, int32_t _e) + : f(_f) + , e(_e) + { + } + + DiyFp(double d) + { + union + { + double d; + uint64_t u64; + } u = { d }; + + int32_t biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) + { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else + { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const + { + BX_CHECK(e == rhs.e, ""); + BX_CHECK(f >= rhs.f, ""); + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const + { + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); + } + + DiyFp Normalize() const + { + uint32_t s = uint64_cntlz(f); + return DiyFp(f << s, e - s); + } + + DiyFp NormalizeBoundary() const + { + uint32_t index = uint64_cntlz(f); + return DiyFp (f << index, e - index); + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const + { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + +#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(l)) + + static const int32_t kDiySignificandSize = 64; + static const int32_t kDpSignificandSize = 52; + static const int32_t kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int32_t kDpMinExponent = -kDpExponentBias; + static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int32_t e; + }; + + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t s_kCachedPowers_F[] = + { + UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76), + UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea), + UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df), + UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f), + UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c), + UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5), + UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d), + UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637), + UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7), + UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5), + UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b), + UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996), + UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8), + UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053), + UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd), + UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94), + UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b), + UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac), + UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3), + UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb), + UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c), + UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000), + UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984), + UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70), + UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245), + UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8), + UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a), + UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea), + UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85), + UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2), + UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3), + UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25), + UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece), + UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5), + UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a), + UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a), + UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129), + UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429), + UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d), + UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841), + UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9), + UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + + static const int16_t s_kCachedPowers_E[] = + { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + + static const char s_cDigitsLut[200] = + { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', + '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', + '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', + '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', + '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', + '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', + '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', + '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', + '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' + }; + + static const uint32_t s_kPow10[] = + { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; + + DiyFp GetCachedPower(int32_t e, int32_t* K) + { + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int32_t k = static_cast<int32_t>(dk); + if (k != dk) + { + k++; + } + + uint32_t index = static_cast<uint32_t>((k >> 3) + 1); + *K = -(-348 + static_cast<int32_t>(index << 3)); // decimal exponent no need lookup table + + BX_CHECK(index < sizeof(s_kCachedPowers_F) / sizeof(s_kCachedPowers_F[0])); + return DiyFp(s_kCachedPowers_F[index], s_kCachedPowers_E[index]); + } + + void GrisuRound(char* buffer, int32_t len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) + { + while (rest < wp_w + && delta - rest >= ten_kappa + && (rest + ten_kappa < wp_w || wp_w - rest > rest + ten_kappa - wp_w)) + { + buffer[len - 1]--; + rest += ten_kappa; + } + } + + uint32_t CountDecimalDigit32(uint32_t n) + { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + if (n < 1000000000) return 9; + return 10; + } + + void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int32_t* len, int32_t* K) + { + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int32_t kappa = static_cast<int32_t>(CountDecimalDigit32(p1)); + *len = 0; + + while (kappa > 0) + { + uint32_t d; + switch (kappa) + { + case 10: d = p1 / 1000000000; p1 %= 1000000000; break; + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default: + d = 0; + break; + } + + if (d || *len) + { + buffer[(*len)++] = '0' + static_cast<char>(d); + } + + kappa--; + uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2; + if (tmp <= delta) + { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(s_kPow10[kappa]) << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) + { + p2 *= 10; + delta *= 10; + char d = static_cast<char>(p2 >> -one.e); + if (d || *len) + { + buffer[(*len)++] = '0' + d; + } + + p2 &= one.f - 1; + kappa--; + if (p2 < delta) + { + *K += kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * s_kPow10[-kappa]); + return; + } + } + } + + void Grisu2(double value, char* buffer, int32_t* length, int32_t* K) + { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); + } + + int32_t WriteExponent(int32_t K, char* buffer) + { + const char* ptr = buffer; + + if (K < 0) + { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) + { + *buffer++ = '0' + static_cast<char>(K / 100); + K %= 100; + const char* d = s_cDigitsLut + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) + { + const char* d = s_cDigitsLut + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + { + *buffer++ = '0' + static_cast<char>(K); + } + + *buffer = '\0'; + + return int32_t(buffer - ptr); + } + + int32_t Prettify(char* buffer, int32_t length, int32_t k) + { + const int32_t kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (length <= kk && kk <= 21) + { + // 1234e7 -> 12340000000 + for (int32_t i = length; i < kk; i++) + { + buffer[i] = '0'; + } + + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + buffer[kk + 2] = '\0'; + return kk + 2; + } + + if (0 < kk && kk <= 21) + { + // 1234e-2 -> 12.34 + memmove(&buffer[kk + 1], &buffer[kk], length - kk); + buffer[kk] = '.'; + buffer[length + 1] = '\0'; + return length + 1; + } + + if (-6 < kk && kk <= 0) + { + // 1234e-6 -> 0.001234 + const int32_t offset = 2 - kk; + memmove(&buffer[offset], &buffer[0], length); + buffer[0] = '0'; + buffer[1] = '.'; + for (int32_t i = 2; i < offset; i++) + { + buffer[i] = '0'; + } + + buffer[length + offset] = '\0'; + return length + offset; + } + + if (length == 1) + { + // 1e30 + buffer[1] = 'e'; + int32_t exp = WriteExponent(kk - 1, &buffer[2]); + return 2 + exp; + } + + // 1234e30 -> 1.234e33 + memmove(&buffer[2], &buffer[1], length - 1); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + int32_t exp = WriteExponent(kk - 1, &buffer[length + 2]); + return length + 2 + exp; + } + + int32_t toString(char* _dst, size_t _max, double value) + { + if (isNan(value) ) + { + return (int32_t)strlncpy(_dst, _max, "NaN"); + } + else if (isInfinite(value) ) + { + return (int32_t)strlncpy(_dst, _max, "Inf"); + } + + int32_t sign = 0.0 > value ? 1 : 0; + if (1 == sign) + { + *_dst++ = '-'; + --_max; + value = -value; + } + + int32_t len; + if (0.0 == value) + { + len = (int32_t)strlncpy(_dst, _max, "0.0"); + } + else + { + int32_t kk; + Grisu2(value, _dst, &len, &kk); + len = Prettify(_dst, len, kk); + } + + return len + sign; + } + + static void reverse(char* _dst, size_t _len) + { + for (size_t ii = 0, jj = _len - 1; ii < jj; ++ii, --jj) + { + xchg(_dst[ii], _dst[jj]); + } + } + + int32_t toString(char* _dst, size_t _max, int32_t _value, uint32_t _base) + { + if (_base == 10 + && _value < 0) + { + if (_max < 1) + { + return 0; + } + + _max = toString(_dst + 1, _max - 1, uint32_t(-_value), _base); + if (_max == 0) + { + return 0; + } + + *_dst = '-'; + return int32_t(_max + 1); + } + + return toString(_dst, _max, uint32_t(_value), _base); + } + + int32_t toString(char* _dst, size_t _max, uint32_t _value, uint32_t _base) + { + char data[32]; + size_t len = 0; + + if (_base > 16 + || _base < 2) + { + return 0; + } + + do + { + const uint32_t rem = _value % _base; + _value /= _base; + if (rem < 10) + { + data[len++] = char('0' + rem); + } + else + { + data[len++] = char('a' + rem - 10); + } + + } while (_value != 0); + + if (_max < len + 1) + { + return 0; + } + + reverse(data, len); + + memcpy(_dst, data, len); + _dst[len] = '\0'; + return int32_t(len); + } + +} // namespace bx diff --git a/3rdparty/bx/src/fpumath.cpp b/3rdparty/bx/src/fpumath.cpp new file mode 100644 index 00000000000..da463e08767 --- /dev/null +++ b/3rdparty/bx/src/fpumath.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/fpumath.h> + +namespace bx +{ + const float pi = 3.14159265358979323846f; + const float invPi = 1.0f/3.14159265358979323846f; + const float piHalf = 1.57079632679489661923f; + const float sqrt2 = 1.41421356237309504880f; +#if BX_COMPILER_MSVC + const float huge = float(HUGE_VAL); +#else + const float huge = HUGE_VALF; +#endif // BX_COMPILER_MSVC + + void mtx3Inverse(float* __restrict _result, const float* __restrict _a) + { + float xx = _a[0]; + float xy = _a[1]; + float xz = _a[2]; + float yx = _a[3]; + float yy = _a[4]; + float yz = _a[5]; + float zx = _a[6]; + float zy = _a[7]; + float zz = _a[8]; + + float det = 0.0f; + det += xx * (yy*zz - yz*zy); + det -= xy * (yx*zz - yz*zx); + det += xz * (yx*zy - yy*zx); + + float invDet = 1.0f/det; + + _result[0] = +(yy*zz - yz*zy) * invDet; + _result[1] = -(xy*zz - xz*zy) * invDet; + _result[2] = +(xy*yz - xz*yy) * invDet; + + _result[3] = -(yx*zz - yz*zx) * invDet; + _result[4] = +(xx*zz - xz*zx) * invDet; + _result[5] = -(xx*yz - xz*yx) * invDet; + + _result[6] = +(yx*zy - yy*zx) * invDet; + _result[7] = -(xx*zy - xy*zx) * invDet; + _result[8] = +(xx*yy - xy*yx) * invDet; + } + + void mtxInverse(float* __restrict _result, const float* __restrict _a) + { + float xx = _a[ 0]; + float xy = _a[ 1]; + float xz = _a[ 2]; + float xw = _a[ 3]; + float yx = _a[ 4]; + float yy = _a[ 5]; + float yz = _a[ 6]; + float yw = _a[ 7]; + float zx = _a[ 8]; + float zy = _a[ 9]; + float zz = _a[10]; + float zw = _a[11]; + float wx = _a[12]; + float wy = _a[13]; + float wz = _a[14]; + float ww = _a[15]; + + float det = 0.0f; + det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) ); + det -= xy * (yx*(zz*ww - zw*wz) - yz*(zx*ww - zw*wx) + yw*(zx*wz - zz*wx) ); + det += xz * (yx*(zy*ww - zw*wy) - yy*(zx*ww - zw*wx) + yw*(zx*wy - zy*wx) ); + det -= xw * (yx*(zy*wz - zz*wy) - yy*(zx*wz - zz*wx) + yz*(zx*wy - zy*wx) ); + + float invDet = 1.0f/det; + + _result[ 0] = +(yy*(zz*ww - wz*zw) - yz*(zy*ww - wy*zw) + yw*(zy*wz - wy*zz) ) * invDet; + _result[ 1] = -(xy*(zz*ww - wz*zw) - xz*(zy*ww - wy*zw) + xw*(zy*wz - wy*zz) ) * invDet; + _result[ 2] = +(xy*(yz*ww - wz*yw) - xz*(yy*ww - wy*yw) + xw*(yy*wz - wy*yz) ) * invDet; + _result[ 3] = -(xy*(yz*zw - zz*yw) - xz*(yy*zw - zy*yw) + xw*(yy*zz - zy*yz) ) * invDet; + + _result[ 4] = -(yx*(zz*ww - wz*zw) - yz*(zx*ww - wx*zw) + yw*(zx*wz - wx*zz) ) * invDet; + _result[ 5] = +(xx*(zz*ww - wz*zw) - xz*(zx*ww - wx*zw) + xw*(zx*wz - wx*zz) ) * invDet; + _result[ 6] = -(xx*(yz*ww - wz*yw) - xz*(yx*ww - wx*yw) + xw*(yx*wz - wx*yz) ) * invDet; + _result[ 7] = +(xx*(yz*zw - zz*yw) - xz*(yx*zw - zx*yw) + xw*(yx*zz - zx*yz) ) * invDet; + + _result[ 8] = +(yx*(zy*ww - wy*zw) - yy*(zx*ww - wx*zw) + yw*(zx*wy - wx*zy) ) * invDet; + _result[ 9] = -(xx*(zy*ww - wy*zw) - xy*(zx*ww - wx*zw) + xw*(zx*wy - wx*zy) ) * invDet; + _result[10] = +(xx*(yy*ww - wy*yw) - xy*(yx*ww - wx*yw) + xw*(yx*wy - wx*yy) ) * invDet; + _result[11] = -(xx*(yy*zw - zy*yw) - xy*(yx*zw - zx*yw) + xw*(yx*zy - zx*yy) ) * invDet; + + _result[12] = -(yx*(zy*wz - wy*zz) - yy*(zx*wz - wx*zz) + yz*(zx*wy - wx*zy) ) * invDet; + _result[13] = +(xx*(zy*wz - wy*zz) - xy*(zx*wz - wx*zz) + xz*(zx*wy - wx*zy) ) * invDet; + _result[14] = -(xx*(yy*wz - wy*yz) - xy*(yx*wz - wx*yz) + xz*(yx*wy - wx*yy) ) * invDet; + _result[15] = +(xx*(yy*zz - zy*yz) - xy*(yx*zz - zx*yz) + xz*(yx*zy - zx*yy) ) * invDet; + } + +} // namespace bx diff --git a/3rdparty/bx/src/mutex.cpp b/3rdparty/bx/src/mutex.cpp new file mode 100644 index 00000000000..00e517684e2 --- /dev/null +++ b/3rdparty/bx/src/mutex.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/mutex.h> + +#if BX_CONFIG_SUPPORTS_THREADING + +#if 0 \ + || BX_PLATFORM_ANDROID \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_OSX +# include <pthread.h> +#elif 0 \ + || BX_PLATFORM_WINDOWS \ + || BX_PLATFORM_WINRT \ + || BX_PLATFORM_XBOX360 +# include <errno.h> +#endif // BX_PLATFORM_ + +namespace bx +{ +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + typedef CRITICAL_SECTION pthread_mutex_t; + typedef unsigned pthread_mutexattr_t; + + inline int pthread_mutex_lock(pthread_mutex_t* _mutex) + { + EnterCriticalSection(_mutex); + return 0; + } + + inline int pthread_mutex_unlock(pthread_mutex_t* _mutex) + { + LeaveCriticalSection(_mutex); + return 0; + } + + inline int pthread_mutex_trylock(pthread_mutex_t* _mutex) + { + return TryEnterCriticalSection(_mutex) ? 0 : EBUSY; + } + + inline int pthread_mutex_init(pthread_mutex_t* _mutex, pthread_mutexattr_t* /*_attr*/) + { +#if BX_PLATFORM_WINRT + InitializeCriticalSectionEx(_mutex, 4000, 0); // docs recommend 4000 spincount as sane default +#else + InitializeCriticalSection(_mutex); +#endif + return 0; + } + + inline int pthread_mutex_destroy(pthread_mutex_t* _mutex) + { + DeleteCriticalSection(_mutex); + return 0; + } +#endif // BX_PLATFORM_ + + Mutex::Mutex() + { + pthread_mutexattr_t attr; +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT +#else + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_WINRT + pthread_mutex_init(&m_handle, &attr); + } + + Mutex::~Mutex() + { + pthread_mutex_destroy(&m_handle); + } + + void Mutex::lock() + { + pthread_mutex_lock(&m_handle); + } + + void Mutex::unlock() + { + pthread_mutex_unlock(&m_handle); + } + +} // namespace bx + +#endif // BX_MUTEX_H_HEADER_GUARD diff --git a/3rdparty/bx/src/os.cpp b/3rdparty/bx/src/os.cpp new file mode 100644 index 00000000000..5f1d45945b7 --- /dev/null +++ b/3rdparty/bx/src/os.cpp @@ -0,0 +1,454 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/os.h> +#include <bx/uint32_t.h> +#include <bx/string.h> + +#include <stdio.h> + +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT +# include <windows.h> +# include <psapi.h> +#elif BX_PLATFORM_ANDROID \ + || BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_HURD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_RPI \ + || BX_PLATFORM_STEAMLINK +# include <sched.h> // sched_yield +# if BX_PLATFORM_BSD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_STEAMLINK +# include <pthread.h> // mach_port_t +# endif // BX_PLATFORM_* + +# include <time.h> // nanosleep +# if !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL +# include <dlfcn.h> // dlopen, dlclose, dlsym +# endif // !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL + +# if BX_PLATFORM_ANDROID +# include <malloc.h> // mallinfo +# elif BX_PLATFORM_LINUX \ + || BX_PLATFORM_RPI \ + || BX_PLATFORM_STEAMLINK +# include <unistd.h> // syscall +# include <sys/syscall.h> +# elif BX_PLATFORM_OSX +# include <mach/mach.h> // mach_task_basic_info +# elif BX_PLATFORM_HURD +# include <pthread/pthread.h> // pthread_self +# elif BX_PLATFORM_ANDROID +# include "debug.h" // getTid is not implemented... +# endif // BX_PLATFORM_ANDROID +#endif // BX_PLATFORM_ + +#if BX_CRT_MSVC +# include <direct.h> // _getcwd +#else +# include <unistd.h> // getcwd +#endif // BX_CRT_MSVC + +namespace bx +{ + + void sleep(uint32_t _ms) + { +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 + ::Sleep(_ms); +#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + BX_UNUSED(_ms); + debugOutput("sleep is not implemented"); debugBreak(); +#else + timespec req = {(time_t)_ms/1000, (long)((_ms%1000)*1000000)}; + timespec rem = {0, 0}; + ::nanosleep(&req, &rem); +#endif // BX_PLATFORM_ + } + + void yield() + { +#if BX_PLATFORM_WINDOWS + ::SwitchToThread(); +#elif BX_PLATFORM_XBOX360 + ::Sleep(0); +#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + debugOutput("yield is not implemented"); debugBreak(); +#else + ::sched_yield(); +#endif // BX_PLATFORM_ + } + + uint32_t getTid() + { +#if BX_PLATFORM_WINDOWS + return ::GetCurrentThreadId(); +#elif BX_PLATFORM_LINUX || BX_PLATFORM_RPI || BX_PLATFORM_STEAMLINK + return (pid_t)::syscall(SYS_gettid); +#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX + return (mach_port_t)::pthread_mach_thread_np(pthread_self() ); +#elif BX_PLATFORM_BSD || BX_PLATFORM_NACL + // Casting __nc_basic_thread_data*... need better way to do this. + return *(uint32_t*)::pthread_self(); +#elif BX_PLATFORM_HURD + return (pthread_t)::pthread_self(); +#else +//# pragma message "not implemented." + debugOutput("getTid is not implemented"); debugBreak(); + return 0; +#endif // + } + + size_t getProcessMemoryUsed() + { +#if BX_PLATFORM_ANDROID + struct mallinfo mi = mallinfo(); + return mi.uordblks; +#elif BX_PLATFORM_LINUX || BX_PLATFORM_HURD + FILE* file = fopen("/proc/self/statm", "r"); + if (NULL == file) + { + return 0; + } + + long pages = 0; + int items = fscanf(file, "%*s%ld", &pages); + fclose(file); + return 1 == items + ? pages * sysconf(_SC_PAGESIZE) + : 0 + ; +#elif BX_PLATFORM_OSX +# if defined(MACH_TASK_BASIC_INFO) + mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + + int const result = task_info(mach_task_self() + , MACH_TASK_BASIC_INFO + , (task_info_t)&info + , &infoCount + ); +# else // MACH_TASK_BASIC_INFO + task_basic_info info; + mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT; + + int const result = task_info(mach_task_self() + , TASK_BASIC_INFO + , (task_info_t)&info + , &infoCount + ); +# endif // MACH_TASK_BASIC_INFO + if (KERN_SUCCESS != result) + { + return 0; + } + + return info.resident_size; +#elif BX_PLATFORM_WINDOWS + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(GetCurrentProcess() + , &pmc + , sizeof(pmc) + ); + return pmc.WorkingSetSize; +#else + return 0; +#endif // BX_PLATFORM_* + } + + void* dlopen(const char* _filePath) + { +#if BX_PLATFORM_WINDOWS + return (void*)::LoadLibraryA(_filePath); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_filePath); + return NULL; +#else + return ::dlopen(_filePath, RTLD_LOCAL|RTLD_LAZY); +#endif // BX_PLATFORM_ + } + + void dlclose(void* _handle) + { +#if BX_PLATFORM_WINDOWS + ::FreeLibrary( (HMODULE)_handle); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_handle); +#else + ::dlclose(_handle); +#endif // BX_PLATFORM_ + } + + void* dlsym(void* _handle, const char* _symbol) + { +#if BX_PLATFORM_WINDOWS + return (void*)::GetProcAddress( (HMODULE)_handle, _symbol); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_handle, _symbol); + return NULL; +#else + return ::dlsym(_handle, _symbol); +#endif // BX_PLATFORM_ + } + + bool getenv(const char* _name, char* _out, uint32_t* _inOutSize) + { +#if BX_PLATFORM_WINDOWS + DWORD len = ::GetEnvironmentVariableA(_name, _out, *_inOutSize); + bool result = len != 0 && len < *_inOutSize; + *_inOutSize = len; + return result; +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name, _out, _inOutSize); + return false; +#else + const char* ptr = ::getenv(_name); + uint32_t len = 0; + bool result = false; + if (NULL != ptr) + { + len = (uint32_t)strnlen(ptr); + + result = len != 0 && len < *_inOutSize; + if (len < *_inOutSize) + { + strcpy(_out, ptr); + } + } + + *_inOutSize = len; + return result; +#endif // BX_PLATFORM_ + } + + void setenv(const char* _name, const char* _value) + { +#if BX_PLATFORM_WINDOWS + ::SetEnvironmentVariableA(_name, _value); +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name, _value); +#else + ::setenv(_name, _value, 1); +#endif // BX_PLATFORM_ + } + + void unsetenv(const char* _name) + { +#if BX_PLATFORM_WINDOWS + ::SetEnvironmentVariableA(_name, NULL); +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name); +#else + ::unsetenv(_name); +#endif // BX_PLATFORM_ + } + + int chdir(const char* _path) + { +#if BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_path); + return -1; +#elif BX_CRT_MSVC + return ::_chdir(_path); +#else + return ::chdir(_path); +#endif // BX_COMPILER_ + } + + char* pwd(char* _buffer, uint32_t _size) + { +#if BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_buffer, _size); + return NULL; +#elif BX_CRT_MSVC + return ::_getcwd(_buffer, (int)_size); +#else + return ::getcwd(_buffer, _size); +#endif // BX_COMPILER_ + } + + bool getTempPath(char* _out, uint32_t* _inOutSize) + { +#if BX_PLATFORM_WINDOWS + uint32_t len = ::GetTempPathA(*_inOutSize, _out); + bool result = len != 0 && len < *_inOutSize; + *_inOutSize = len; + return result; +#else + static const char* s_tmp[] = + { + "TMPDIR", + "TMP", + "TEMP", + "TEMPDIR", + + NULL + }; + + for (const char** tmp = s_tmp; *tmp != NULL; ++tmp) + { + uint32_t len = *_inOutSize; + *_out = '\0'; + bool result = getenv(*tmp, _out, &len); + + if (result + && len != 0 + && len < *_inOutSize) + { + *_inOutSize = len; + return result; + } + } + + FileInfo fi; + if (stat("/tmp", fi) + && FileInfo::Directory == fi.m_type) + { + strlncpy(_out, *_inOutSize, "/tmp"); + *_inOutSize = 4; + return true; + } + + return false; +#endif // BX_PLATFORM_* + } + + bool stat(const char* _filePath, FileInfo& _fileInfo) + { + _fileInfo.m_size = 0; + _fileInfo.m_type = FileInfo::Count; + +#if BX_COMPILER_MSVC + struct ::_stat64 st; + int32_t result = ::_stat64(_filePath, &st); + + if (0 != result) + { + return false; + } + + if (0 != (st.st_mode & _S_IFREG) ) + { + _fileInfo.m_type = FileInfo::Regular; + } + else if (0 != (st.st_mode & _S_IFDIR) ) + { + _fileInfo.m_type = FileInfo::Directory; + } +#else + struct ::stat st; + int32_t result = ::stat(_filePath, &st); + if (0 != result) + { + return false; + } + + if (0 != (st.st_mode & S_IFREG) ) + { + _fileInfo.m_type = FileInfo::Regular; + } + else if (0 != (st.st_mode & S_IFDIR) ) + { + _fileInfo.m_type = FileInfo::Directory; + } +#endif // BX_COMPILER_MSVC + + _fileInfo.m_size = st.st_size; + + return true; + } + + void* exec(const char* const* _argv) + { +#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD + pid_t pid = fork(); + + if (0 == pid) + { + int result = execvp(_argv[0], const_cast<char *const*>(&_argv[1]) ); + BX_UNUSED(result); + return NULL; + } + + return (void*)uintptr_t(pid); +#elif BX_PLATFORM_WINDOWS + STARTUPINFO si; + memset(&si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(STARTUPINFO); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(PROCESS_INFORMATION) ); + + int32_t total = 0; + for (uint32_t ii = 0; NULL != _argv[ii]; ++ii) + { + total += (int32_t)strnlen(_argv[ii]) + 1; + } + + char* temp = (char*)alloca(total); + int32_t len = 0; + for(uint32_t ii = 0; NULL != _argv[ii]; ++ii) + { + len += snprintf(&temp[len], bx::uint32_imax(0, total-len) + , "%s " + , _argv[ii] + ); + } + + bool ok = !!CreateProcessA(_argv[0] + , temp + , NULL + , NULL + , false + , 0 + , NULL + , NULL + , &si + , &pi + ); + if (ok) + { + return pi.hProcess; + } + + return NULL; +#else + BX_UNUSED(_argv); + return NULL; +#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD + } + +} // namespace bx diff --git a/3rdparty/bx/src/sem.cpp b/3rdparty/bx/src/sem.cpp new file mode 100644 index 00000000000..2d3ca1574f8 --- /dev/null +++ b/3rdparty/bx/src/sem.cpp @@ -0,0 +1,221 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/sem.h> + +#if BX_CONFIG_SUPPORTS_THREADING + +#if BX_PLATFORM_POSIX +# include <errno.h> +# include <semaphore.h> +# include <time.h> +# include <pthread.h> +#elif BX_PLATFORM_XBOXONE +# include <synchapi.h> +#elif BX_PLATFORM_XBOX360 || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT +# include <windows.h> +# include <limits.h> +#endif // BX_PLATFORM_ + +namespace bx +{ +#if BX_PLATFORM_POSIX + +# if BX_CONFIG_SEMAPHORE_PTHREAD + Semaphore::Semaphore() + : m_count(0) + { + int result; + result = pthread_mutex_init(&m_mutex, NULL); + BX_CHECK(0 == result, "pthread_mutex_init %d", result); + + result = pthread_cond_init(&m_cond, NULL); + BX_CHECK(0 == result, "pthread_cond_init %d", result); + + BX_UNUSED(result); + } + + Semaphore::~Semaphore() + { + int result; + result = pthread_cond_destroy(&m_cond); + BX_CHECK(0 == result, "pthread_cond_destroy %d", result); + + result = pthread_mutex_destroy(&m_mutex); + BX_CHECK(0 == result, "pthread_mutex_destroy %d", result); + + BX_UNUSED(result); + } + + void Semaphore::post(uint32_t _count) + { + int result = pthread_mutex_lock(&m_mutex); + BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + + for (uint32_t ii = 0; ii < _count; ++ii) + { + result = pthread_cond_signal(&m_cond); + BX_CHECK(0 == result, "pthread_cond_signal %d", result); + } + + m_count += _count; + + result = pthread_mutex_unlock(&m_mutex); + BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + + BX_UNUSED(result); + } + + bool Semaphore::wait(int32_t _msecs) + { + int result = pthread_mutex_lock(&m_mutex); + BX_CHECK(0 == result, "pthread_mutex_lock %d", result); + +# if BX_PLATFORM_NACL || BX_PLATFORM_OSX + BX_UNUSED(_msecs); + BX_CHECK(-1 == _msecs, "NaCl and OSX don't support pthread_cond_timedwait at this moment."); + while (0 == result + && 0 >= m_count) + { + result = pthread_cond_wait(&m_cond, &m_mutex); + } +# elif BX_PLATFORM_IOS + if (-1 == _msecs) + { + while (0 == result + && 0 >= m_count) + { + result = pthread_cond_wait(&m_cond, &m_mutex); + } + } + else + { + timespec ts; + ts.tv_sec = _msecs/1000; + ts.tv_nsec = (_msecs%1000)*1000; + + while (0 == result + && 0 >= m_count) + { + result = pthread_cond_timedwait_relative_np(&m_cond, &m_mutex, &ts); + } + } +# else + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += _msecs/1000; + ts.tv_nsec += (_msecs%1000)*1000; + + while (0 == result + && 0 >= m_count) + { + result = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); + } +# endif // BX_PLATFORM_NACL || BX_PLATFORM_OSX + bool ok = 0 == result; + + if (ok) + { + --m_count; + } + + result = pthread_mutex_unlock(&m_mutex); + BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); + + BX_UNUSED(result); + + return ok; + } + +# else + + Semaphore::Semaphore() + { + int32_t result = sem_init(&m_handle, 0, 0); + BX_CHECK(0 == result, "sem_init failed. errno %d", errno); + BX_UNUSED(result); + } + + Semaphore::~Semaphore() + { + int32_t result = sem_destroy(&m_handle); + BX_CHECK(0 == result, "sem_destroy failed. errno %d", errno); + BX_UNUSED(result); + } + + void Semaphore::post(uint32_t _count) + { + int32_t result; + for (uint32_t ii = 0; ii < _count; ++ii) + { + result = sem_post(&m_handle); + BX_CHECK(0 == result, "sem_post failed. errno %d", errno); + } + BX_UNUSED(result); + } + + bool Semaphore::wait(int32_t _msecs) + { +# if BX_PLATFORM_NACL || BX_PLATFORM_OSX + BX_CHECK(-1 == _msecs, "NaCl and OSX don't support sem_timedwait at this moment."); BX_UNUSED(_msecs); + return 0 == sem_wait(&m_handle); +# else + if (0 > _msecs) + { + int32_t result; + do + { + result = sem_wait(&m_handle); + } // keep waiting when interrupted by a signal handler... + while (-1 == result && EINTR == errno); + BX_CHECK(0 == result, "sem_wait failed. errno %d", errno); + return 0 == result; + } + + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += _msecs/1000; + ts.tv_nsec += (_msecs%1000)*1000; + return 0 == sem_timedwait(&m_handle, &ts); +# endif // BX_PLATFORM_ + } +# endif // BX_CONFIG_SEMAPHORE_PTHREAD + +#elif BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT + + Semaphore::Semaphore() + { +#if BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + m_handle = CreateSemaphoreExW(NULL, 0, LONG_MAX, NULL, 0, SEMAPHORE_ALL_ACCESS); +#else + m_handle = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL); +#endif + BX_CHECK(NULL != m_handle, "Failed to create Semaphore!"); + } + + Semaphore::~Semaphore() + { + CloseHandle(m_handle); + } + + void Semaphore::post(uint32_t _count) + { + ReleaseSemaphore(m_handle, _count, NULL); + } + + bool Semaphore::wait(int32_t _msecs) + { + DWORD milliseconds = (0 > _msecs) ? INFINITE : _msecs; +#if BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + return WAIT_OBJECT_0 == WaitForSingleObjectEx(m_handle, milliseconds, FALSE); +#else + return WAIT_OBJECT_0 == WaitForSingleObject(m_handle, milliseconds); +#endif + } +#endif // BX_PLATFORM_ + +} // namespace bx + +#endif // BX_CONFIG_SUPPORTS_THREADING diff --git a/3rdparty/bx/src/string.cpp b/3rdparty/bx/src/string.cpp new file mode 100644 index 00000000000..c53a9de1155 --- /dev/null +++ b/3rdparty/bx/src/string.cpp @@ -0,0 +1,515 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/allocator.h> +#include <bx/hash.h> +#include <bx/readerwriter.h> +#include <bx/string.h> + +#if !BX_CRT_NONE +# include <stdio.h> // vsnprintf, vsnwprintf +#endif // !BX_CRT_NONE + +namespace bx +{ + bool isSpace(char _ch) + { + return ' ' == _ch + || '\t' == _ch + || '\n' == _ch + || '\v' == _ch + || '\f' == _ch + || '\r' == _ch + ; + } + + bool isUpper(char _ch) + { + return _ch >= 'A' && _ch <= 'Z'; + } + + bool isLower(char _ch) + { + return _ch >= 'a' && _ch <= 'z'; + } + + bool isAlpha(char _ch) + { + return isLower(_ch) || isUpper(_ch); + } + + bool isNumeric(char _ch) + { + return _ch >= '0' && _ch <= '9'; + } + + bool isAlphaNum(char _ch) + { + return isAlpha(_ch) || isNumeric(_ch); + } + + bool isPrint(char _ch) + { + return isAlphaNum(_ch) || isSpace(_ch); + } + + char toLower(char _ch) + { + return _ch + (isUpper(_ch) ? 0x20 : 0); + } + + char toUpper(char _ch) + { + return _ch - (isLower(_ch) ? 0x20 : 0); + } + + bool toBool(const char* _str) + { + char ch = toLower(_str[0]); + return ch == 't' || ch == '1'; + } + + int32_t strncmp(const char* _lhs, const char* _rhs, size_t _max) + { + for ( + ; 0 < _max && *_lhs == *_rhs + ; ++_lhs, ++_rhs, --_max + ) + { + if (*_lhs == '\0' + || *_rhs == '\0') + { + break; + } + } + + return 0 == _max ? 0 : *_lhs - *_rhs; + } + + int32_t strincmp(const char* _lhs, const char* _rhs, size_t _max) + { + for ( + ; 0 < _max && toLower(*_lhs) == toLower(*_rhs) + ; ++_lhs, ++_rhs, --_max + ) + { + if (*_lhs == '\0' + || *_rhs == '\0') + { + break; + } + } + + return 0 == _max ? 0 : *_lhs - *_rhs; + } + + size_t strnlen(const char* _str, size_t _max) + { + const char* ptr; + for (ptr = _str; 0 < _max && *ptr != '\0'; ++ptr, --_max) {}; + return ptr - _str; + } + + size_t strlncpy(char* _dst, size_t _dstSize, const char* _src, size_t _num) + { + BX_CHECK(NULL != _dst, "_dst can't be NULL!"); + BX_CHECK(NULL != _src, "_src can't be NULL!"); + BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + + const size_t len = strnlen(_src, _num); + const size_t max = _dstSize-1; + const size_t num = (len < max ? len : max); + memcpy(_dst, _src, num); + _dst[num] = '\0'; + + return num; + } + + size_t strlncat(char* _dst, size_t _dstSize, const char* _src, size_t _num) + { + BX_CHECK(NULL != _dst, "_dst can't be NULL!"); + BX_CHECK(NULL != _src, "_src can't be NULL!"); + BX_CHECK(0 < _dstSize, "_dstSize can't be 0!"); + + const size_t max = _dstSize; + const size_t len = strnlen(_dst, max); + return strlncpy(&_dst[len], max-len, _src, _num); + } + + const char* strnchr(const char* _str, char _ch, size_t _max) + { + for (size_t ii = 0, len = strnlen(_str, _max); ii < len; ++ii) + { + if (_str[ii] == _ch) + { + return &_str[ii]; + } + } + + return NULL; + } + + const char* strnrchr(const char* _str, char _ch, size_t _max) + { + for (size_t ii = strnlen(_str, _max); 0 < ii; --ii) + { + if (_str[ii] == _ch) + { + return &_str[ii]; + } + } + + return NULL; + } + + const char* strnstr(const char* _str, const char* _find, size_t _max) + { + const char* ptr = _str; + + size_t stringLen = strnlen(_str, _max); + const size_t findLen = strnlen(_find); + + for (; stringLen >= findLen; ++ptr, --stringLen) + { + // Find start of the string. + while (*ptr != *_find) + { + ++ptr; + --stringLen; + + // Search pattern lenght can't be longer than the string. + if (findLen > stringLen) + { + return NULL; + } + } + + // Set pointers. + const char* string = ptr; + const char* search = _find; + + // Start comparing. + while (*string++ == *search++) + { + // If end of the 'search' string is reached, all characters match. + if ('\0' == *search) + { + return ptr; + } + } + } + + return NULL; + } + + const char* stristr(const char* _str, const char* _find, size_t _max) + { + const char* ptr = _str; + + size_t stringLen = strnlen(_str, _max); + const size_t findLen = strnlen(_find); + + for (; stringLen >= findLen; ++ptr, --stringLen) + { + // Find start of the string. + while (toLower(*ptr) != toLower(*_find) ) + { + ++ptr; + --stringLen; + + // Search pattern lenght can't be longer than the string. + if (findLen > stringLen) + { + return NULL; + } + } + + // Set pointers. + const char* string = ptr; + const char* search = _find; + + // Start comparing. + while (toLower(*string++) == toLower(*search++) ) + { + // If end of the 'search' string is reached, all characters match. + if ('\0' == *search) + { + return ptr; + } + } + } + + return NULL; + } + + const char* strnl(const char* _str) + { + for (; '\0' != *_str; _str += strnlen(_str, 1024) ) + { + const char* eol = strnstr(_str, "\r\n", 1024); + if (NULL != eol) + { + return eol + 2; + } + + eol = strnstr(_str, "\n", 1024); + if (NULL != eol) + { + return eol + 1; + } + } + + return _str; + } + + const char* streol(const char* _str) + { + for (; '\0' != *_str; _str += strnlen(_str, 1024) ) + { + const char* eol = strnstr(_str, "\r\n", 1024); + if (NULL != eol) + { + return eol; + } + + eol = strnstr(_str, "\n", 1024); + if (NULL != eol) + { + return eol; + } + } + + return _str; + } + + const char* strws(const char* _str) + { + for (; isSpace(*_str); ++_str) {}; + return _str; + } + + const char* strnws(const char* _str) + { + for (; !isSpace(*_str); ++_str) {}; + return _str; + } + + const char* strword(const char* _str) + { + for (char ch = *_str++; isAlphaNum(ch) || '_' == ch; ch = *_str++) {}; + return _str-1; + } + + const char* strmb(const char* _str, char _open, char _close) + { + int count = 0; + for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++) + { + if (ch == _open) + { + count++; + } + else if (ch == _close) + { + count--; + if (0 == count) + { + return _str-1; + } + } + } + + return NULL; + } + + void eolLF(char* _out, size_t _size, const char* _str) + { + if (0 < _size) + { + char* end = _out + _size - 1; + for (char ch = *_str++; ch != '\0' && _out < end; ch = *_str++) + { + if ('\r' != ch) + { + *_out++ = ch; + } + } + + *_out = '\0'; + } + } + + const char* findIdentifierMatch(const char* _str, const char* _word) + { + size_t len = strnlen(_word); + const char* ptr = strnstr(_str, _word); + for (; NULL != ptr; ptr = strnstr(ptr + len, _word) ) + { + if (ptr != _str) + { + char ch = *(ptr - 1); + if (isAlphaNum(ch) || '_' == ch) + { + continue; + } + } + + char ch = ptr[len]; + if (isAlphaNum(ch) || '_' == ch) + { + continue; + } + + return ptr; + } + + return ptr; + } + + const char* findIdentifierMatch(const char* _str, const char* _words[]) + { + for (const char* word = *_words; NULL != word; ++_words, word = *_words) + { + const char* match = findIdentifierMatch(_str, word); + if (NULL != match) + { + return match; + } + } + + return NULL; + } + + int32_t write(WriterI* _writer, const char* _format, va_list _argList, Error* _err); + + int32_t vsnprintfRef(char* _out, size_t _max, const char* _format, va_list _argList) + { + if (1 < _max) + { + StaticMemoryBlockWriter writer(_out, _max-1); + _out[_max-1] = '\0'; + + Error err; + va_list argListCopy; + va_copy(argListCopy, _argList); + int32_t size = write(&writer, _format, argListCopy, &err); + va_end(argListCopy); + + if (err.isOk() ) + { + return size; + } + } + + Error err; + SizerWriter sizer; + va_list argListCopy; + va_copy(argListCopy, _argList); + int32_t size = write(&sizer, _format, argListCopy, &err); + va_end(argListCopy); + + return size - 1 /* size without '\0' terminator */; + } + + int32_t vsnprintf(char* _out, size_t _max, const char* _format, va_list _argList) + { +#if BX_CRT_NONE + return vsnprintfRef(_out, _max, _format, _argList); +#elif BX_CRT_MSVC + int32_t len = -1; + if (NULL != _out) + { + va_list argListCopy; + va_copy(argListCopy, _argList); + len = ::vsnprintf_s(_out, _max, size_t(-1), _format, argListCopy); + va_end(argListCopy); + } + return -1 == len ? ::_vscprintf(_format, _argList) : len; +#else + return ::vsnprintf(_out, _max, _format, _argList); +#endif // BX_COMPILER_MSVC + } + + int32_t snprintf(char* _out, size_t _max, const char* _format, ...) + { + va_list argList; + va_start(argList, _format); + int32_t len = vsnprintf(_out, _max, _format, argList); + va_end(argList); + return len; + } + + int32_t vsnwprintf(wchar_t* _out, size_t _max, const wchar_t* _format, va_list _argList) + { +#if BX_CRT_NONE + BX_UNUSED(_out, _max, _format, _argList); + return 0; +#elif BX_CRT_MSVC + int32_t len = -1; + if (NULL != _out) + { + va_list argListCopy; + va_copy(argListCopy, _argList); + len = ::_vsnwprintf_s(_out, _max, size_t(-1), _format, argListCopy); + va_end(argListCopy); + } + return -1 == len ? ::_vscwprintf(_format, _argList) : len; +#elif BX_CRT_MINGW + return ::vsnwprintf(_out, _max, _format, _argList); +#else + return ::vswprintf(_out, _max, _format, _argList); +#endif // BX_COMPILER_MSVC + } + + int32_t swnprintf(wchar_t* _out, size_t _max, const wchar_t* _format, ...) + { + va_list argList; + va_start(argList, _format); + int32_t len = vsnwprintf(_out, _max, _format, argList); + va_end(argList); + return len; + } + + const char* baseName(const char* _filePath) + { + const char* bs = strnrchr(_filePath, '\\'); + const char* fs = strnrchr(_filePath, '/'); + const char* slash = (bs > fs ? bs : fs); + const char* colon = strnrchr(_filePath, ':'); + const char* basename = slash > colon ? slash : colon; + if (NULL != basename) + { + return basename+1; + } + + return _filePath; + } + + void prettify(char* _out, size_t _count, uint64_t _size) + { + uint8_t idx = 0; + double size = double(_size); + while (_size != (_size&0x7ff) + && idx < 9) + { + _size >>= 10; + size *= 1.0/1024.0; + ++idx; + } + + snprintf(_out, _count, "%0.2f %c%c", size, "BkMGTPEZY"[idx], idx > 0 ? 'B' : '\0'); + } + + size_t strlcpy(char* _dst, const char* _src, size_t _max) + { + return strlncpy(_dst, _max, _src); + } + + size_t strlcat(char* _dst, const char* _src, size_t _max) + { + return strlncat(_dst, _max, _src); + } + +} // namespace bx diff --git a/3rdparty/bx/src/thread.cpp b/3rdparty/bx/src/thread.cpp new file mode 100644 index 00000000000..fea7e8b606c --- /dev/null +++ b/3rdparty/bx/src/thread.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/thread.h> + +#if BX_CONFIG_SUPPORTS_THREADING + +namespace bx +{ + Thread::Thread() +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + : m_handle(INVALID_HANDLE_VALUE) + , m_threadId(UINT32_MAX) +#elif BX_PLATFORM_POSIX + : m_handle(0) +#endif // BX_PLATFORM_ + , m_fn(NULL) + , m_userData(NULL) + , m_stackSize(0) + , m_exitCode(0 /*EXIT_SUCCESS*/) + , m_running(false) + { + } + + Thread::~Thread() + { + if (m_running) + { + shutdown(); + } + } + + void Thread::init(ThreadFn _fn, void* _userData, uint32_t _stackSize, const char* _name) + { + BX_CHECK(!m_running, "Already running!"); + + m_fn = _fn; + m_userData = _userData; + m_stackSize = _stackSize; + m_running = true; + +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE + m_handle = ::CreateThread(NULL + , m_stackSize + , (LPTHREAD_START_ROUTINE)threadFunc + , this + , 0 + , NULL + ); +#elif BX_PLATFORM_WINRT + m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^) + { + m_exitCode = threadFunc(this); + SetEvent(m_handle); + }, CallbackContext::Any); + + ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced); +#elif BX_PLATFORM_POSIX + int result; + BX_UNUSED(result); + + pthread_attr_t attr; + result = pthread_attr_init(&attr); + BX_CHECK(0 == result, "pthread_attr_init failed! %d", result); + + if (0 != m_stackSize) + { + result = pthread_attr_setstacksize(&attr, m_stackSize); + BX_CHECK(0 == result, "pthread_attr_setstacksize failed! %d", result); + } + + // sched_param sched; + // sched.sched_priority = 0; + // result = pthread_attr_setschedparam(&attr, &sched); + // BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); + + result = pthread_create(&m_handle, &attr, &threadFunc, this); + BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result); +#else +# error "Not implemented!" +#endif // BX_PLATFORM_ + + m_sem.wait(); + + if (NULL != _name) + { + setThreadName(_name); + } + } + + void Thread::shutdown() + { + BX_CHECK(m_running, "Not running!"); +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 + WaitForSingleObject(m_handle, INFINITE); + GetExitCodeThread(m_handle, (DWORD*)&m_exitCode); + CloseHandle(m_handle); + m_handle = INVALID_HANDLE_VALUE; +#elif BX_PLATFORM_WINRT + WaitForSingleObjectEx(m_handle, INFINITE, FALSE); + CloseHandle(m_handle); + m_handle = INVALID_HANDLE_VALUE; +#elif BX_PLATFORM_POSIX + union + { + void* ptr; + int32_t i; + } cast; + pthread_join(m_handle, &cast.ptr); + m_exitCode = cast.i; + m_handle = 0; +#endif // BX_PLATFORM_ + m_running = false; + } + + bool Thread::isRunning() const + { + return m_running; + } + + int32_t Thread::getExitCode() const + { + return m_exitCode; + } + + void Thread::setThreadName(const char* _name) + { +#if BX_PLATFORM_OSX || BX_PLATFORM_IOS + pthread_setname_np(_name); +#elif (BX_CRT_GLIBC >= 21200) && ! BX_PLATFORM_HURD + pthread_setname_np(m_handle, _name); +#elif BX_PLATFORM_LINUX + prctl(PR_SET_NAME,_name, 0, 0, 0); +#elif BX_PLATFORM_BSD +# ifdef __NetBSD__ + pthread_setname_np(m_handle, "%s", (void*)_name); +# else + pthread_set_name_np(m_handle, _name); +# endif // __NetBSD__ +#elif BX_PLATFORM_WINDOWS && BX_COMPILER_MSVC +# pragma pack(push, 8) + struct ThreadName + { + DWORD type; + LPCSTR name; + DWORD id; + DWORD flags; + }; +# pragma pack(pop) + ThreadName tn; + tn.type = 0x1000; + tn.name = _name; + tn.id = m_threadId; + tn.flags = 0; + + __try + { + RaiseException(0x406d1388 + , 0 + , sizeof(tn)/4 + , reinterpret_cast<ULONG_PTR*>(&tn) + ); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +#else + BX_UNUSED(_name); +#endif // BX_PLATFORM_ + } + + int32_t Thread::entry() + { +#if BX_PLATFORM_WINDOWS + m_threadId = ::GetCurrentThreadId(); +#endif // BX_PLATFORM_WINDOWS + + m_sem.post(); + return m_fn(m_userData); + } + +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + DWORD WINAPI Thread::threadFunc(LPVOID _arg) + { + Thread* thread = (Thread*)_arg; + int32_t result = thread->entry(); + return result; + } +#else + void* Thread::threadFunc(void* _arg) + { + Thread* thread = (Thread*)_arg; + union + { + void* ptr; + int32_t i; + } cast; + cast.i = thread->entry(); + return cast.ptr; + } +#endif // BX_PLATFORM_ + +} // namespace bx + +#endif // BX_CONFIG_SUPPORTS_THREADING diff --git a/3rdparty/bx/tests/dbg.cpp b/3rdparty/bx/tests/dbg.cpp deleted file mode 100644 index 58e3f034a86..00000000000 --- a/3rdparty/bx/tests/dbg.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2011-2017 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bx#license-bsd-2-clause - */ - -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <ctype.h> // isprint - -#include "dbg.h" -#include <bx/string.h> -#include <bx/debug.h> - -void dbgPrintfVargs(const char* _format, va_list _argList) -{ - char temp[8192]; - char* out = temp; - int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); - if ( (int32_t)sizeof(temp) < len) - { - out = (char*)alloca(len+1); - len = bx::vsnprintf(out, len, _format, _argList); - } - out[len] = '\0'; - bx::debugOutput(out); -} - -void dbgPrintf(const char* _format, ...) -{ - va_list argList; - va_start(argList, _format); - dbgPrintfVargs(_format, argList); - va_end(argList); -} - -#define DBG_ADDRESS "%" PRIxPTR - -void dbgPrintfData(const void* _data, uint32_t _size, const char* _format, ...) -{ -#define HEX_DUMP_WIDTH 16 -#define HEX_DUMP_SPACE_WIDTH 48 -#define HEX_DUMP_FORMAT "%-" DBG_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." DBG_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s" - - va_list argList; - va_start(argList, _format); - dbgPrintfVargs(_format, argList); - va_end(argList); - - dbgPrintf("\ndata: " DBG_ADDRESS ", size: %d\n", _data, _size); - - if (NULL != _data) - { - const uint8_t* data = reinterpret_cast<const uint8_t*>(_data); - char hex[HEX_DUMP_WIDTH*3+1]; - char ascii[HEX_DUMP_WIDTH+1]; - uint32_t hexPos = 0; - uint32_t asciiPos = 0; - for (uint32_t ii = 0; ii < _size; ++ii) - { - bx::snprintf(&hex[hexPos], sizeof(hex)-hexPos, "%02x ", data[asciiPos]); - hexPos += 3; - - ascii[asciiPos] = isprint(data[asciiPos]) ? data[asciiPos] : '.'; - asciiPos++; - - if (HEX_DUMP_WIDTH == asciiPos) - { - ascii[asciiPos] = '\0'; - dbgPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); - data += asciiPos; - hexPos = 0; - asciiPos = 0; - } - } - - if (0 != asciiPos) - { - ascii[asciiPos] = '\0'; - dbgPrintf("\t" DBG_ADDRESS "\t" HEX_DUMP_FORMAT "\t%s\n", data, hex, ascii); - } - } - -#undef HEX_DUMP_WIDTH -#undef HEX_DUMP_SPACE_WIDTH -#undef HEX_DUMP_FORMAT -} diff --git a/3rdparty/bx/tests/dbg.h b/3rdparty/bx/tests/dbg.h index 21f4433820b..9ae46b35bbe 100644 --- a/3rdparty/bx/tests/dbg.h +++ b/3rdparty/bx/tests/dbg.h @@ -6,16 +6,11 @@ #ifndef DBG_H_HEADER_GUARD #define DBG_H_HEADER_GUARD -#include <stdarg.h> // va_list -#include <stdint.h> +#include <bx/debug.h> #define DBG_STRINGIZE(_x) DBG_STRINGIZE_(_x) #define DBG_STRINGIZE_(_x) #_x #define DBG_FILE_LINE_LITERAL "" __FILE__ "(" DBG_STRINGIZE(__LINE__) "): " -#define DBG(_format, ...) dbgPrintf(DBG_FILE_LINE_LITERAL "" _format "\n", ##__VA_ARGS__) - -extern void dbgPrintfVargs(const char* _format, va_list _argList); -extern void dbgPrintf(const char* _format, ...); -extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format, ...); +#define DBG(_format, ...) bx::debugPrintf(DBG_FILE_LINE_LITERAL "" _format "\n", ##__VA_ARGS__) #endif // DBG_H_HEADER_GUARD diff --git a/3rdparty/bx/tests/fpumath_test.cpp b/3rdparty/bx/tests/fpumath_test.cpp index f41cea8ba91..ae843872e43 100644 --- a/3rdparty/bx/tests/fpumath_test.cpp +++ b/3rdparty/bx/tests/fpumath_test.cpp @@ -6,6 +6,26 @@ #include "test.h" #include <bx/fpumath.h> +#if !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800 +#include <cmath> +TEST_CASE("isFinite, isInfinite, isNan", "") +{ + for (uint64_t ii = 0; ii < UINT32_MAX; ii += rand()%(1<<13)+1) + { + union { uint32_t ui; float f; } u = { uint32_t(ii) }; + REQUIRE(std::isnan(u.f) == bx::isNan(u.f) ); + REQUIRE(std::isfinite(u.f) == bx::isFinite(u.f) ); + REQUIRE(std::isinf(u.f) == bx::isInfinite(u.f) ); + } +} +#endif // !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800 + +TEST_CASE("ToBits", "") +{ + REQUIRE(UINT32_C(0x12345678) == bx::floatToBits( bx::bitsToFloat( UINT32_C(0x12345678) ) ) ); + REQUIRE(UINT64_C(0x123456789abcdef0) == bx::doubleToBits(bx::bitsToDouble(UINT32_C(0x123456789abcdef0) ) ) ); +} + void mtxCheck(const float* _a, const float* _b) { if (!bx::fequal(_a, _b, 16, 0.01f) ) @@ -35,7 +55,7 @@ void mtxCheck(const float* _a, const float* _b) } } -TEST(Quaternion) +TEST_CASE("quaternion", "") { float mtxQ[16]; float mtx[16]; diff --git a/3rdparty/bx/tests/handle_bench.cpp b/3rdparty/bx/tests/handle_bench.cpp index a882cbe635d..6169bc45c53 100644 --- a/3rdparty/bx/tests/handle_bench.cpp +++ b/3rdparty/bx/tests/handle_bench.cpp @@ -28,13 +28,13 @@ int main() for (uint32_t jj = 0; jj < numElements; ++jj) { tinystl::pair<TinyStlUnorderedMap::iterator, bool> ok = map.insert(tinystl::make_pair(uint64_t(jj), uint16_t(jj) ) ); - assert(ok.second); + assert(ok.second); BX_UNUSED(ok); } for (uint32_t jj = 0; jj < numElements; ++jj) { bool ok = bx::mapRemove(map, uint64_t(jj) ); - assert(ok); + assert(ok); BX_UNUSED(ok); } assert(map.size() == 0); @@ -56,13 +56,13 @@ int main() for (uint32_t jj = 0; jj < numElements; ++jj) { std::pair<StdUnorderedMap::iterator, bool> ok = map.insert(std::make_pair(uint64_t(jj), uint16_t(jj) ) ); - assert(ok.second); + assert(ok.second); BX_UNUSED(ok); } for (uint32_t jj = 0; jj < numElements; ++jj) { bool ok = bx::mapRemove(map, uint64_t(jj) ); - assert(ok); + assert(ok); BX_UNUSED(ok); } assert(map.size() == 0); @@ -83,13 +83,13 @@ int main() for (uint32_t jj = 0; jj < numElements; ++jj) { bool ok = map.insert(jj, uint16_t(jj) ); - assert(ok); + assert(ok); BX_UNUSED(ok); } for (uint32_t jj = 0; jj < numElements; ++jj) { bool ok = map.removeByKey(uint64_t(jj) ); - assert(ok); + assert(ok); BX_UNUSED(ok); } assert(map.getNumElements() == 0); diff --git a/3rdparty/bx/tests/misc_test.cpp b/3rdparty/bx/tests/misc_test.cpp deleted file mode 100644 index aec1067a022..00000000000 --- a/3rdparty/bx/tests/misc_test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "test.h" -#include <bx/os.h> - -TEST(getProcessMemoryUsed) -{ - CHECK(0 != bx::getProcessMemoryUsed() ); -// DBG("bx::getProcessMemoryUsed %d", bx::getProcessMemoryUsed() ); -} diff --git a/3rdparty/bx/tests/os_test.cpp b/3rdparty/bx/tests/os_test.cpp new file mode 100644 index 00000000000..e6aeb314fbe --- /dev/null +++ b/3rdparty/bx/tests/os_test.cpp @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include "test.h" +#include <bx/os.h> + +TEST_CASE("getProcessMemoryUsed", "") +{ + REQUIRE(0 != bx::getProcessMemoryUsed() ); +// DBG("bx::getProcessMemoryUsed %d", bx::getProcessMemoryUsed() ); +} + +TEST_CASE("getTempPath", "") +{ + char tmpDir[512]; + uint32_t len = BX_COUNTOF(tmpDir); + REQUIRE(bx::getTempPath(tmpDir, &len) ); +} diff --git a/3rdparty/bx/tests/string_test.cpp b/3rdparty/bx/tests/string_test.cpp index ed83e86cc4d..bea72044e54 100644 --- a/3rdparty/bx/tests/string_test.cpp +++ b/3rdparty/bx/tests/string_test.cpp @@ -10,6 +10,19 @@ bx::AllocatorI* g_allocator; +TEST_CASE("chars", "") +{ + for (char ch = 'A'; ch <= 'Z'; ++ch) + { + REQUIRE(!bx::isLower(ch) ); + REQUIRE(!bx::isNumeric(ch) ); + REQUIRE(bx::isUpper(ch) ); + REQUIRE(bx::isAlpha(ch) ); + REQUIRE(bx::isAlphaNum(ch) ); + REQUIRE(bx::isLower(bx::toLower(ch) ) ); + } +} + TEST_CASE("strnlen", "") { const char* test = "test"; @@ -40,6 +53,129 @@ TEST_CASE("strlncpy", "") REQUIRE(num == 4); } +TEST_CASE("strlncat", "") +{ + char dst[128] = { '\0' }; + + REQUIRE(0 == bx::strlncat(dst, 1, "cat") ); + + REQUIRE(4 == bx::strlncpy(dst, 5, "copy") ); + REQUIRE(3 == bx::strlncat(dst, 8, "cat") ); + REQUIRE(0 == bx::strncmp(dst, "copycat") ); + + REQUIRE(1 == bx::strlncat(dst, BX_COUNTOF(dst), "------", 1) ); + REQUIRE(3 == bx::strlncat(dst, BX_COUNTOF(dst), "cat") ); + REQUIRE(0 == bx::strncmp(dst, "copycat-cat") ); +} + +TEST_CASE("strincmp", "") +{ + REQUIRE(0 == bx::strincmp("test", "test") ); + REQUIRE(0 == bx::strincmp("test", "testestes", 4) ); + REQUIRE(0 == bx::strincmp("testestes", "test", 4) ); + REQUIRE(0 != bx::strincmp("preprocess", "platform") ); + + const char* abvgd = "abvgd"; + const char* abvgx = "abvgx"; + const char* empty = ""; + REQUIRE(0 == bx::strincmp(abvgd, abvgd) ); + REQUIRE(0 == bx::strincmp(abvgd, abvgx, 4) ); + + REQUIRE(0 > bx::strincmp(abvgd, abvgx) ); + REQUIRE(0 > bx::strincmp(empty, abvgd) ); + + REQUIRE(0 < bx::strincmp(abvgx, abvgd) ); + REQUIRE(0 < bx::strincmp(abvgd, empty) ); +} + +TEST_CASE("strnchr", "") +{ + const char* test = "test"; + REQUIRE(NULL == bx::strnchr(test, 's', 0) ); + REQUIRE(NULL == bx::strnchr(test, 's', 2) ); + REQUIRE(&test[2] == bx::strnchr(test, 's') ); +} + +TEST_CASE("strnrchr", "") +{ + const char* test = "test"; + REQUIRE(NULL == bx::strnrchr(test, 's', 0) ); + REQUIRE(NULL == bx::strnrchr(test, 's', 1) ); + REQUIRE(&test[2] == bx::strnrchr(test, 's') ); +} + +TEST_CASE("stristr", "") +{ + const char* test = "The Quick Brown Fox Jumps Over The Lazy Dog."; + + REQUIRE(NULL == bx::stristr(test, "quick", 8) ); + REQUIRE(NULL == bx::stristr(test, "quick1") ); + REQUIRE(&test[4] == bx::stristr(test, "quick", 9) ); + REQUIRE(&test[4] == bx::stristr(test, "quick") ); +} + +TEST_CASE("strnstr", "") +{ + const char* test = "The Quick Brown Fox Jumps Over The Lazy Dog."; + + REQUIRE(NULL == bx::strnstr(test, "quick", 8) ); + REQUIRE(NULL == bx::strnstr(test, "quick1") ); + REQUIRE(NULL == bx::strnstr(test, "quick", 9) ); + REQUIRE(NULL == bx::strnstr(test, "quick") ); + + REQUIRE(NULL == bx::strnstr(test, "Quick", 8) ); + REQUIRE(NULL == bx::strnstr(test, "Quick1") ); + REQUIRE(&test[4] == bx::strnstr(test, "Quick", 9) ); + REQUIRE(&test[4] == bx::strnstr(test, "Quick") ); +} + +template<typename Ty> +static bool testToString(Ty _value, const char* _expected) +{ + char tmp[1024]; + int32_t num = bx::toString(tmp, BX_COUNTOF(tmp), _value); + int32_t len = (int32_t)bx::strnlen(_expected); + return true + && 0 == bx::strncmp(tmp, _expected) + && num == len + ; +} + +TEST_CASE("toString int32_t/uint32_t", "") +{ + REQUIRE(testToString(0, "0") ); + REQUIRE(testToString(-256, "-256") ); + REQUIRE(testToString(INT32_MAX, "2147483647") ); + REQUIRE(testToString(UINT32_MAX, "4294967295") ); +} + +TEST_CASE("toString double", "") +{ + REQUIRE(testToString(0.0, "0.0") ); + REQUIRE(testToString(-0.0, "0.0") ); + REQUIRE(testToString(1.0, "1.0") ); + REQUIRE(testToString(-1.0, "-1.0") ); + REQUIRE(testToString(1.2345, "1.2345") ); + REQUIRE(testToString(1.2345678, "1.2345678") ); + REQUIRE(testToString(0.123456789012, "0.123456789012") ); + REQUIRE(testToString(1234567.8, "1234567.8") ); + REQUIRE(testToString(-79.39773355813419, "-79.39773355813419") ); + REQUIRE(testToString(0.000001, "0.000001") ); + REQUIRE(testToString(0.0000001, "1e-7") ); + REQUIRE(testToString(1e30, "1e30") ); + REQUIRE(testToString(1.234567890123456e30, "1.234567890123456e30") ); + REQUIRE(testToString(-5e-324, "-5e-324") ); + REQUIRE(testToString(2.225073858507201e-308, "2.225073858507201e-308") ); + REQUIRE(testToString(2.2250738585072014e-308, "2.2250738585072014e-308") ); + REQUIRE(testToString(1.7976931348623157e308, "1.7976931348623157e308") ); + REQUIRE(testToString(0.00000123123123, "0.00000123123123") ); + REQUIRE(testToString(0.000000123123123, "1.23123123e-7") ); + REQUIRE(testToString(123123.123, "123123.123") ); + REQUIRE(testToString(1231231.23, "1231231.23") ); + REQUIRE(testToString(0.000000000123123, "1.23123e-10") ); + REQUIRE(testToString(0.0000000001, "1e-10") ); +} + TEST_CASE("StringView", "") { bx::StringView sv("test"); diff --git a/3rdparty/bx/tests/test.h b/3rdparty/bx/tests/test.h index 33c3cf7cbc0..db710195023 100644 --- a/3rdparty/bx/tests/test.h +++ b/3rdparty/bx/tests/test.h @@ -13,8 +13,4 @@ #include "dbg.h" -#if !BX_COMPILER_MSVC -# define _strdup strdup -#endif // !BX_COMPILER_MSVC - #endif // __TEST_H__ diff --git a/3rdparty/bx/tests/tokenizecmd_test.cpp b/3rdparty/bx/tests/tokenizecmd_test.cpp index 12502502a1a..7d35ac7484c 100644 --- a/3rdparty/bx/tests/tokenizecmd_test.cpp +++ b/3rdparty/bx/tests/tokenizecmd_test.cpp @@ -4,7 +4,6 @@ */ #include "test.h" -#include <bx/tokenizecmd.h> #include <bx/commandline.h> #include <string.h> @@ -14,6 +13,8 @@ TEST(commandLine) { "-s", "--long", + "--platform", + "x", }; bx::CommandLine cmdLine(BX_COUNTOF(args), args); @@ -23,6 +24,7 @@ TEST(commandLine) // non-existing argument CHECK(!cmdLine.hasArg('x') ); + CHECK(!cmdLine.hasArg("preprocess") ); } TEST(tokenizeCommandLine) diff --git a/3rdparty/bx/tests/uint32_test.cpp b/3rdparty/bx/tests/uint32_test.cpp index 0c2be1e9cb7..ae214b88c22 100644 --- a/3rdparty/bx/tests/uint32_test.cpp +++ b/3rdparty/bx/tests/uint32_test.cpp @@ -6,47 +6,66 @@ #include "test.h" #include <bx/uint32_t.h> -TEST(StrideAlign) +TEST_CASE("StrideAlign") { - CHECK(0 == bx::strideAlign(0, 12) ); + REQUIRE(0 == bx::strideAlign(0, 12) ); for (uint32_t ii = 0; ii < 12; ++ii) { - CHECK(12 == bx::strideAlign(ii+1, 12) ); + REQUIRE(12 == bx::strideAlign(ii+1, 12) ); } - CHECK(0 == bx::strideAlign16(0, 12) ); + REQUIRE(0 == bx::strideAlign16(0, 12) ); for (uint32_t ii = 0; ii < 12; ++ii) { - CHECK(48 == bx::strideAlign16(ii+1, 12) ); + REQUIRE(48 == bx::strideAlign16(ii+1, 12) ); } } -TEST(uint32_cnt) +TEST_CASE("uint32_cnt") { - CHECK( 0 == bx::uint32_cnttz(UINT32_C(1) ) ); - CHECK( 0 == bx::uint32_cnttz_ref(UINT32_C(1) ) ); + REQUIRE( 0 == bx::uint32_cnttz(UINT32_C(1) ) ); + REQUIRE( 0 == bx::uint32_cnttz_ref(UINT32_C(1) ) ); - CHECK(31 == bx::uint32_cntlz(UINT32_C(1) ) ); - CHECK(31 == bx::uint32_cntlz_ref(UINT32_C(1) ) ); + REQUIRE(31 == bx::uint32_cntlz(UINT32_C(1) ) ); + REQUIRE(31 == bx::uint32_cntlz_ref(UINT32_C(1) ) ); - CHECK( 0 == bx::uint64_cnttz(UINT64_C(1) ) ); - CHECK( 0 == bx::uint64_cnttz_ref(UINT64_C(1) ) ); + REQUIRE( 0 == bx::uint64_cnttz(UINT64_C(1) ) ); + REQUIRE( 0 == bx::uint64_cnttz_ref(UINT64_C(1) ) ); - CHECK(63 == bx::uint64_cntlz(UINT64_C(1) ) ); - CHECK(63 == bx::uint64_cntlz_ref(UINT64_C(1) ) ); + REQUIRE(63 == bx::uint64_cntlz(UINT64_C(1) ) ); + REQUIRE(63 == bx::uint64_cntlz_ref(UINT64_C(1) ) ); - CHECK( 1 == bx::uint32_cntbits(1) ); - CHECK( 1 == bx::uint32_cntbits_ref(1) ); + REQUIRE( 1 == bx::uint32_cntbits(1) ); + REQUIRE( 1 == bx::uint32_cntbits_ref(1) ); - CHECK(16 == bx::uint32_cntbits(UINT16_MAX) ); - CHECK(16 == bx::uint32_cntbits_ref(UINT16_MAX) ); + REQUIRE(16 == bx::uint32_cntbits(UINT16_MAX) ); + REQUIRE(16 == bx::uint32_cntbits_ref(UINT16_MAX) ); - CHECK(32 == bx::uint32_cntbits(UINT32_MAX) ); - CHECK(32 == bx::uint32_cntbits_ref(UINT32_MAX) ); + REQUIRE(32 == bx::uint32_cntbits(UINT32_MAX) ); + REQUIRE(32 == bx::uint32_cntbits_ref(UINT32_MAX) ); } -TEST(uint32_part) +TEST_CASE("uint32_part") { - CHECK(UINT32_C(0x55555555) == bx::uint32_part1by1(UINT16_MAX) ); - CHECK(UINT32_C(0x09249249) == bx::uint32_part1by2(0x3ff) ); + REQUIRE(UINT32_C(0x55555555) == bx::uint32_part1by1(UINT16_MAX) ); + REQUIRE(UINT32_C(0x09249249) == bx::uint32_part1by2(0x3ff) ); +} + +TEST_CASE("halfTo/FromFloat", "") +{ + for (uint32_t ii = 0; ii < 0x7c00; ++ii) + { + const uint16_t orig = uint16_t(ii); + const float htf = bx::halfToFloat(orig); + const uint16_t hff = bx::halfFromFloat(htf); + REQUIRE(orig == hff); + } + + for (uint32_t ii = 0x8000; ii < 0xfc00; ++ii) + { + const uint16_t orig = uint16_t(ii); + const float htf = bx::halfToFloat(orig); + const uint16_t hff = bx::halfFromFloat(htf); + REQUIRE(orig == hff); + } } diff --git a/3rdparty/bx/tests/vector_complex_test.cpp b/3rdparty/bx/tests/vector_complex_test.cpp index 8deaa3fd3ff..a540ece8a40 100644 --- a/3rdparty/bx/tests/vector_complex_test.cpp +++ b/3rdparty/bx/tests/vector_complex_test.cpp @@ -33,6 +33,10 @@ #include <string.h> #include <stdlib.h> +#if !BX_COMPILER_MSVC +# define _strdup strdup +#endif // !BX_COMPILER_MSVC + struct complex { complex() {data = 0;} complex(const char* s) { data = strdup(s); } @@ -156,7 +160,7 @@ TEST(vector_complex_popback) { v.push_back("24"); CHECK(v.back() == "24"); - + v.pop_back(); CHECK(v.back() == "12"); diff --git a/3rdparty/bx/tests/vsnprintf_test.cpp b/3rdparty/bx/tests/vsnprintf_test.cpp new file mode 100644 index 00000000000..db1fba6fdad --- /dev/null +++ b/3rdparty/bx/tests/vsnprintf_test.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include "test.h" +#include <bx/string.h> + +TEST_CASE("vsnprintf NULL buffer", "No output buffer provided.") +{ + REQUIRE(4 == bx::snprintf(NULL, 0, "test") ); + + REQUIRE(1 == bx::snprintf(NULL, 0, "%d", 1) ); +} + +TEST_CASE("vsnprintf truncated", "Truncated output buffer.") +{ + char buffer[7]; + + REQUIRE(10 == bx::snprintf(buffer, BX_COUNTOF(buffer), "Ten chars!") ); + REQUIRE(0 == strcmp(buffer, "Ten ch") ); +} + +static bool test(const char* _expected, const char* _format, ...) +{ + int32_t max = (int32_t)strlen(_expected) + 1; + char* temp = (char*)alloca(max); + + va_list argList; + va_start(argList, _format); + int32_t len = bx::vsnprintf(temp, max, _format, argList); + va_end(argList); + + bool result = true + && len == max-1 + && 0 == strcmp(_expected, temp) + ; + + if (!result) + { + printf("result (%d) %s, expected (%d) %s\n", len, temp, max-1, _expected); + } + + return result; +} + +TEST_CASE("vsnprintf f", "") +{ + REQUIRE(test("1.337", "%0.3f", 1.337) ); + REQUIRE(test(" 13.370", "%8.3f", 13.37) ); + REQUIRE(test(" 13.370", "%*.*f", 8, 3, 13.37) ); + REQUIRE(test("13.370 ", "%-8.3f", 13.37) ); + REQUIRE(test("13.370 ", "%*.*f", -8, 3, 13.37) ); +} + +TEST_CASE("vsnprintf d/u/x", "") +{ + REQUIRE(test("1337", "%d", 1337) ); + + REQUIRE(test("1337", "%x", 0x1337) ); +} + +TEST_CASE("vsnprintf", "") +{ + REQUIRE(test("x", "%c", 'x') ); + + REQUIRE(test("hello, world!", "%s, %s!", "hello", "world") ); +} diff --git a/3rdparty/bx/tools/bin/darwin/genie b/3rdparty/bx/tools/bin/darwin/genie Binary files differindex 842ca082bdf..97c6f1279b9 100755 --- a/3rdparty/bx/tools/bin/darwin/genie +++ b/3rdparty/bx/tools/bin/darwin/genie diff --git a/3rdparty/bx/tools/bin/linux/genie b/3rdparty/bx/tools/bin/linux/genie Binary files differindex 7feeebbd006..3fa52f00f4f 100755 --- a/3rdparty/bx/tools/bin/linux/genie +++ b/3rdparty/bx/tools/bin/linux/genie diff --git a/3rdparty/bx/tools/bin/windows/genie.exe b/3rdparty/bx/tools/bin/windows/genie.exe Binary files differindex ad7d65824d6..19d6f15c6cd 100644 --- a/3rdparty/bx/tools/bin/windows/genie.exe +++ b/3rdparty/bx/tools/bin/windows/genie.exe |