rtengine/src/runtime/runtime.h
Kevin Trogant 5d988d15b7 give passes views instead of lists
A view is a collection of lists. This is useful for a shadow mapping
pass that generates more than one shadow map.
Each view would create lists of objects visible in one shadow map.
2024-05-07 08:12:45 +02:00

217 lines
6.4 KiB
C

#ifndef RT_VOYAGE_H
#define RT_VOYAGE_H
/* basic types and macros */
#include <limits.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER) && !defined(RT_STATIC_LIB)
#define RT_DLLEXPORT __declspec(dllexport)
#define RT_DLLIMPORT __declspec(dllimport)
#else
#define RT_DLLEXPORT
#define RT_DLLIMPORT
#endif
#if defined(_MSC_VER)
#define RT_INLINE __forceinline
#elif defined(__GNUC__) || defined(__clang__)
#define RT_INLINE inline __attribute__((always_inline))
#endif
#define RT_UNUSED(x) ((void)sizeof((x)))
#define RT_ARRAY_COUNT(x) (sizeof((x)) / sizeof((x)[0]))
#define RT_RESTRICT_VALUE_TO_BOUNDS(v, lower, upper) \
(((v) < (lower)) ? (lower) : (((v) > (upper)) ? (upper) : (v)))
#define RT_MIN(a, b) (((a) < (b))?(a):(b))
#define RT_MAX(a, b) (((a) > (b))?(a):(b))
#define RT_KB(n) ((n)*1024U)
#define RT_MB(n) ((n)*1024U * 1024U)
#define RT_GB(n) ((n)*1024U * 1024U * 1024U)
#ifndef __cplusplus
#if defined(_MSC_VER)
/* For some reason _Thread_local does not work with vs2022,
* despite MS documentation claiming it should. */
#define RT_THREAD_LOCAL __declspec(thread)
#elif defined(__GNUC__) || defined(__clang__)
/* _Thread_local in C11-C17, thread_local in C23 */
#if __STDC_VERSION__ > 201710L
#define RT_THREAD_LOCAL thread_local
#elif __STDC_VERSION__ >= 201112L
#define RT_THREAD_LOCAL _Thread_local
#else
#error Versions older than C11 not supported.
#endif
#endif
#else
// C++ 11 supports thread_local
#if __cplusplus >= 201103L
#define RT_THREAD_LOCAL thread_local
#elif defined(_MSC_VER)
#define RT_THREAD_LOCAL __declspec(thread)
#else
#error Versions older than C++11 not supported.
#endif
#endif
/* Matches windows MAX_PATH */
#define RT_PATH_MAX 260
typedef unsigned int rt_result;
/* Default result codes */
enum {
RT_SUCCESS = 0,
RT_OUT_OF_MEMORY = 1,
RT_INVALID_VALUE = 2,
RT_CUSTOM_ERROR_START,
RT_UNKNOWN_ERROR = (rt_result)INT_MAX,
};
typedef struct {
const char *start;
unsigned int length;
} rt_text_span;
/* snprintf replacement.
* Always returns a zero terminated string.
*/
RT_DLLEXPORT int rtSPrint(char *dest, size_t n, const char *fmt, ...);
RT_DLLEXPORT int rtVSPrint(char *dest, size_t n, const char *fmt, va_list ap);
/* Returns results like strcmp():
* - If the first differing character is smaller in span than in cmp: < 0
* - If span and cmp are equal: 0
* - If the first differing character is greater in span than in cmp: > 0
* - If span.length is smaller than strlen(cmp): -1
* - If span.length is greater than strlen(cmp): 1
*/
RT_DLLEXPORT int rtCompareSpanToString(rt_text_span span, const char *cmp);
RT_DLLEXPORT void rtReportError(const char *subsystem, const char *fmt, ...);
RT_DLLEXPORT void rtLog(const char *subsystem, const char *fmt, ...);
#ifndef NDEBUG
#ifdef _MSC_VER
#define RT_DEBUGBREAK __debugbreak()
#elif defined(__clang__) && __has_builtin(__bultin_debugtrap)
#define RT_DEBUGBREAK __builtin_debugtrap()
#elif defined(__GNUC__)
#define RT_DEBUGBREAK __builtin_trap()
#endif
RT_DLLEXPORT int rtAssertHandler(const char *expr, const char *msg, const char *file, int line);
#define RT_ASSERT(x, msg) \
do { \
if (!(x)) { \
if (rtAssertHandler(#x, (msg), __FILE__, __LINE__) == 0) { \
RT_DEBUGBREAK; \
} \
} \
} while (0)
#define RT_ASSERT_ALWAYS_EVAL(x, msg) RT_ASSERT(x, msg)
// Asserts if p is "false", evaluates to p
// NOTE that this will evaluate p multiple times!
#define RT_VERIFY(p) \
((!(p)) ? (rtAssertHandler(#p, "Verify failed", __FILE__, __LINE__), p) : p)
#else
#define RT_ASSERT(x, msg) RT_UNUSED(x)
#define RT_ASSERT_ALWAYS_EVAL(x, msg) (x)
#define RT_VERIFY(p) (p)
#endif
/* Makes it easier to search for unimplemented functions */
#define RT_NOT_IMPLEMENTED RT_ASSERT_ALWAYS_EVAL(0, "Not implemented.")
enum {
RT_INVALID_UNICODE = RT_CUSTOM_ERROR_START,
RT_INSUFFICIENT_BUFFER,
};
/* Returns RT_SUCCESS if the string was successfully converted,
* RT_INVALID_UNICODE if invalid unicode characters were encountered or
* RT_INSUFFICIENT_BUFFER if the provided output buffer is too small */
RT_DLLEXPORT rt_result rtUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len);
/* Returns RT_SUCCESS if the string was successfully converted,
* RT_INVALID_UNICODE if invalid unicode characters were encountered or
* RT_INSUFFICIENT_BUFFER if the provided output buffer is too small */
RT_DLLEXPORT rt_result rtWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len);
/* Relative pointer */
typedef struct {
int32_t off;
} rt_relptr;
static RT_INLINE void *rtResolveRelptr(rt_relptr *ptr) {
if (ptr->off != 0) {
char *p = (char *)ptr;
return (void *)(p + (ptrdiff_t)ptr->off);
} else {
return NULL;
}
}
static RT_INLINE const void *rtResolveConstRelptr(const rt_relptr *ptr) {
if (ptr->off != 0) {
const char *p = (const char *)ptr;
return (const void *)(p + (ptrdiff_t)ptr->off);
} else {
return NULL;
}
}
static RT_INLINE void rtSetRelptr(rt_relptr *ptr, void *target) {
if (target) {
char *p = (char *)ptr, *t = (char *)target;
ptrdiff_t d = t - p;
ptr->off = (int32_t)d;
} else {
ptr->off = 0;
}
}
/* Bitfiddling functions */
/* Portable solution, On x64 using clzl is probably faster. */
static RT_INLINE uint32_t rtNextPowerOfTwo32(uint32_t v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/* Runtime init. Initializes basic systems.
* You need to call this, even if you build a CLI only app. */
RT_DLLEXPORT rt_result rtInitRuntime(void);
RT_DLLEXPORT void rtShutdownRuntime(void);
#ifdef __cplusplus
}
#endif
#endif