Merge branch 'master' into dev

This commit is contained in:
bjorn 2023-01-02 16:46:55 -08:00
commit b6d8546a6f
19 changed files with 996 additions and 2371 deletions

View File

@ -26,6 +26,7 @@ jobs:
name: lovr.exe
path: |
build/Release/lovr.exe
build/Release/lovrc.bat
build/Release/*.dll
linux:
name: Linux

View File

@ -59,6 +59,8 @@ if(EMSCRIPTEN)
set(LOVR_USE_OPENXR OFF)
set(LOVR_USE_WEBGPU ON)
set(LOVR_USE_VULKAN OFF)
elseif(MSVC)
add_compile_options(/MP)
elseif(ANDROID)
find_package(Java REQUIRED)
set(LOVR_USE_DESKTOP OFF)
@ -110,6 +112,11 @@ if(LOVR_USE_LUAJIT AND NOT EMSCRIPTEN)
else()
add_subdirectory(deps/luajit luajit)
set_target_properties(luajit PROPERTIES EXCLUDE_FROM_ALL 1)
if(MSVC)
target_compile_definitions(libluajit PRIVATE _CRT_SECURE_NO_WARNINGS)
target_compile_definitions(minilua PRIVATE _CRT_SECURE_NO_WARNINGS)
target_compile_definitions(buildvm PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()
include_directories(deps/luajit/src ${CMAKE_BINARY_DIR}/luajit)
set(LOVR_LUA libluajit)
endif()
@ -616,18 +623,28 @@ foreach(path ${LOVR_RESOURCES})
endforeach()
# Add a custom target that is always out of date so libraries are always moved
add_custom_target(move_libraries ALL)
add_custom_target(move_files ALL)
# Moves something from etc to the build directory
function(move_resource)
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/etc/${ARGV0}")
add_custom_command(TARGET lovr POST_BUILD
DEPENDS ${SRC}
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} $<TARGET_FILE_DIR:lovr>/${ARGV0}
)
endfunction()
# Platforms
if(WIN32)
target_sources(lovr PRIVATE src/core/os_win32.c)
target_sources(lovr PRIVATE etc/lovr.rc)
if (MSVC)
set_target_properties(lovr PROPERTIES COMPILE_FLAGS "/wd4244 /MP")
set_target_properties(lovr PROPERTIES COMPILE_FLAGS /wd4244)
# Excuse anonymous union for type punning
set_source_files_properties(src/util.c src/modules/graphics/graphics.c PROPERTIES COMPILE_FLAGS /wd4116)
# Excuse unsigned negation for flag-magic bit math
set_source_files_properties(src/modules/audio/audio.c PROPERTIES COMPILE_FLAGS /wd4146)
set_source_files_properties(src/lib/minimp3/minimp3.c PROPERTIES COMPILE_FLAGS /wd4267)
else()
set_target_properties(lovr PROPERTIES COMPILE_FLAGS "-MP")
endif()
@ -644,7 +661,7 @@ if(WIN32)
function(move_dll)
if(TARGET ${ARGV0})
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
$<TARGET_FILE_DIR:lovr>/$<TARGET_FILE_NAME:${ARGV0}>
@ -662,6 +679,7 @@ if(WIN32)
foreach(target ${ALL_PLUGIN_TARGETS})
move_dll(${target})
endforeach()
move_resource("lovrc.bat")
elseif(APPLE)
find_library(AVFOUNDATION AVFoundation)
target_link_libraries(lovr objc ${AVFOUNDATION})
@ -688,13 +706,13 @@ elseif(APPLE)
if(TARGET ${ARGV0})
get_target_property(TARGET_TYPE ${ARGV0} TYPE)
if(${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
${EXE_DIR}/$<TARGET_FILE_NAME:${ARGV0}>
)
else()
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_SONAME_FILE:${ARGV0}>
${EXE_DIR}/$<TARGET_SONAME_FILE_NAME:${ARGV0}>
@ -800,13 +818,13 @@ elseif(ANDROID)
# Copy plugin libraries to lib folder before packaging APK
foreach(target ${ALL_PLUGIN_TARGETS})
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${target}>
raw/lib/${ANDROID_ABI}/$<TARGET_FILE_NAME:${target}>
)
endforeach()
add_dependencies(buildAPK move_libraries)
add_dependencies(buildAPK move_files)
endif()
elseif(UNIX)
target_sources(lovr PRIVATE src/core/os_linux.c)
@ -819,13 +837,13 @@ elseif(UNIX)
if(TARGET ${ARGV0})
get_target_property(TARGET_TYPE ${ARGV0} TYPE)
if(${TARGET_TYPE} STREQUAL "MODULE_LIBRARY")
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${ARGV0}>
${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:${ARGV0}>
)
elseif(${TARGET_TYPE} STREQUAL "SHARED_LIBRARY")
add_custom_command(TARGET move_libraries POST_BUILD
add_custom_command(TARGET move_files POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_SONAME_FILE:${ARGV0}>
${CMAKE_BINARY_DIR}/bin/$<TARGET_SONAME_FILE_NAME:${ARGV0}>
@ -833,14 +851,6 @@ elseif(UNIX)
endif()
endif()
endfunction()
function(move_app_image_file)
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/etc/${ARGV0}")
set(DST "${CMAKE_BINARY_DIR}/bin/${ARGV0}")
add_custom_command(TARGET lovr POST_BUILD
DEPENDS ${SRC}
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
)
endfunction()
move_lib(${LOVR_GLFW})
move_lib(${LOVR_LUA})
move_lib(${LOVR_ODE})
@ -851,8 +861,8 @@ elseif(UNIX)
move_lib(${target})
endforeach()
if(LOVR_BUILD_BUNDLE)
move_app_image_file("lovr.desktop")
move_app_image_file("AppRun")
move_app_image_file("logo.svg")
move_resource("lovr.desktop")
move_resource("AppRun")
move_resource("logo.svg")
endif()
endif()

View File

@ -1,4 +1,4 @@
Copyright (c) 2022 Bjorn Swenson and other LÖVR contributors
Copyright (c) 2023 Bjorn Swenson and other LÖVR contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -8,7 +8,8 @@ You can use LÖVR to easily create VR experiences without much setup or programm
[![Build](https://github.com/bjornbytes/lovr/actions/workflows/build.yml/badge.svg?event=push)](https://github.com/bjornbytes/lovr/actions/workflows/build.yml)
[![Version](https://img.shields.io/github/release/bjornbytes/lovr.svg?label=version)](https://github.com/bjornbytes/lovr/releases)
[![Matrix](https://img.shields.io/badge/chat-matrix-7e4e76.svg)](https://lovr.org/matrix)
[![Matrix](https://img.shields.io/badge/chat-matrix-0ba378.svg)](https://lovr.org/matrix)
[![Discord](https://img.shields.io/badge/chat-discord-404eed.svg)](https://lovr.org/discord)
[**Homepage**](https://lovr.org) | [**Documentation**](https://lovr.org/docs) | [**FAQ**](https://lovr.org/docs/FAQ)

View File

@ -103,7 +103,8 @@ cflags = {
'-Ietc',
'-Isrc',
'-Isrc/modules',
'-Isrc/lib/stdatomic'
'-Isrc/lib/stdatomic',
'-Ideps/vulkan-headers/include'
}
bin = target == 'android' and 'bin/apk/lib/arm64-v8a' or 'bin'

2
deps/msdfgen vendored

@ -1 +1 @@
Subproject commit 3f77ce6ac70e8e558e18f638a77b5bcbbf31ca06
Subproject commit 6f7eda06adc23bc14ca2e14190d69ae1d00f1740

View File

@ -227,7 +227,8 @@ function lovr.threaderror(thread, err)
end
function lovr.log(message, level, tag)
print(message:gsub('\n$', ''))
message = message:gsub('\n$', '')
print(message)
end
return function()

1
etc/lovrc.bat Normal file
View File

@ -0,0 +1 @@
lovr --console %*

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@ io.write('};\n\n')
io.write('uint16_t monkey_indices[] = {\n ')
for i = 1, model:getMeshIndexCount(1) do
local index = model:getMeshIndex(1, i)
local index = model:getMeshIndex(1, i) - 1
io.write((' %d,'):format(index))
if i % 10 == 0 then
io.write('\n ')

View File

@ -26,10 +26,11 @@ static int l_lovrBlobGetString(lua_State* L) {
uint32_t offset = luax_optu32(L, 2, 0);
lovrCheck(offset < blob->size, "Blob byte offset must be less than the size of the Blob");
uint32_t length = luax_optu32(L, 3, blob->size - offset);
lovrCheck(length <= blob->size - offset, "Blob:getString range overflows the length of the Blob");
lua_Integer length = luaL_optinteger(L, 3, blob->size - offset);
lovrCheck(length >= 0, "Length can not be negative");
lovrCheck((size_t) length <= blob->size - offset, "Blob:getString range overflows the length of the Blob");
lua_pushlstring(L, (char*) blob->data + offset, length);
lua_pushlstring(L, (char*) blob->data + offset, (size_t) length);
return 1;
}

View File

@ -386,7 +386,7 @@ static int l_lovrModelDataGetMeshVertex(lua_State* L) {
ModelAttribute* attribute = mesh->attributes[i];
if (!attribute) continue;
uint32_t stride = model->buffers[attribute->buffer].stride;
size_t stride = model->buffers[attribute->buffer].stride;
if (!stride) {
switch (attribute->type) {
@ -697,9 +697,9 @@ static int l_lovrModelDataGetAnimationKeyframe(lua_State* L) {
uint32_t keyframe = luax_checku32(L, 4) - 1;
lovrCheck(keyframe < channel->keyframeCount, "Invalid keyframe index '%d'", keyframe + 1);
lua_pushnumber(L, channel->times[keyframe]);
size_t counts[] = { [PROP_TRANSLATION] = 3, [PROP_ROTATION] = 4, [PROP_SCALE] = 3 };
size_t count = counts[channel->property];
for (uint32_t i = 0; i < count; i++) {
int counts[] = { [PROP_TRANSLATION] = 3, [PROP_ROTATION] = 4, [PROP_SCALE] = 3 };
int count = counts[channel->property];
for (int i = 0; i < count; i++) {
lua_pushnumber(L, channel->data[keyframe * count + i]);
}
return count + 1;

View File

@ -45,7 +45,7 @@ void luax_checkvariant(lua_State* L, int index, Variant* variant) {
const char* string = lua_tolstring(L, index, &length);
if (length <= sizeof(variant->value.ministring.data)) {
variant->type = TYPE_MINISTRING;
variant->value.ministring.length = length;
variant->value.ministring.length = (uint8_t) length;
memcpy(variant->value.ministring.data, string, length);
} else {
variant->type = TYPE_STRING;

View File

@ -150,6 +150,19 @@ static int l_lovrWorldGetColliders(lua_State* L) {
return 1;
}
static int l_lovrWorldGetTags(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lua_newtable(L);
for (uint32_t i = 0; i < MAX_TAGS; i++) {
const char* tag = lovrWorldGetTagName(world, i);
if (tag == NULL)
break;
lua_pushstring(L, tag);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
static int l_lovrWorldDestroy(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lovrWorldDestroyData(world);
@ -371,6 +384,7 @@ const luaL_Reg lovrWorld[] = {
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
{ "newTerrainCollider", l_lovrWorldNewTerrainCollider },
{ "getColliders", l_lovrWorldGetColliders },
{ "getTags", l_lovrWorldGetTags },
{ "destroy", l_lovrWorldDestroy },
{ "update", l_lovrWorldUpdate },
{ "computeOverlaps", l_lovrWorldComputeOverlaps },

View File

@ -188,6 +188,11 @@ static struct {
uint32_t tick[2];
gpu_tick ticks[4];
gpu_morgue morgue;
struct {
bool validation;
bool portability;
bool debug;
} supports;
} state;
// Helpers
@ -1842,79 +1847,72 @@ bool gpu_init(gpu_config* config) {
#endif
GPU_FOREACH_ANONYMOUS(GPU_LOAD_ANONYMOUS);
{ // Instance
struct {
bool validation;
bool portability;
bool debug;
} supports = { 0 };
{
// Layers
struct { const char* name; bool shouldEnable; bool* isEnabled; } layers[] = {
{ "VK_LAYER_KHRONOS_validation", config->debug, &supports.validation }
VkLayerProperties layerInfo[32];
uint32_t layerCount = COUNTOF(layerInfo);
VK(vkEnumerateInstanceLayerProperties(&layerCount, layerInfo), "Failed to enumerate instance layers") return gpu_destroy(), false;
struct { const char* name; bool shouldEnable; bool* flag; } layers[] = {
{ "VK_LAYER_KHRONOS_validation", config->debug, &state.supports.validation }
};
const char* enabledLayers[1];
uint32_t enabledLayerCount = 0;
VkLayerProperties layerInfo[32];
uint32_t count = COUNTOF(layerInfo);
VK(vkEnumerateInstanceLayerProperties(&count, layerInfo), "Failed to enumerate instance layers") return gpu_destroy(), false;
const char* enabledLayers[COUNTOF(layers)];
for (uint32_t i = 0; i < COUNTOF(layers); i++) {
if (!layers[i].shouldEnable) continue;
if (hasLayer(layerInfo, count, layers[i].name)) {
if (hasLayer(layerInfo, layerCount, layers[i].name)) {
CHECK(enabledLayerCount < COUNTOF(enabledLayers), "Too many layers") return gpu_destroy(), false;
if (layers[i].isEnabled) *layers[i].isEnabled = true;
if (layers[i].flag) *layers[i].flag = true;
enabledLayers[enabledLayerCount++] = layers[i].name;
} else if (!layers[i].flag) {
vcheck(VK_ERROR_LAYER_NOT_PRESENT, layers[i].name);
return gpu_destroy(), false;
}
}
// Extensions
struct { const char* name; bool shouldEnable; bool* isEnabled; } extensions[] = {
{ "VK_KHR_portability_enumeration", true, &supports.portability },
{ "VK_EXT_debug_utils", config->debug, &supports.debug }
VkExtensionProperties extensionInfo[64];
uint32_t extensionCount = COUNTOF(extensionInfo);
VK(vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensionInfo), "Failed to enumerate instance extensions") return gpu_destroy(), false;
struct { const char* name; bool shouldEnable; bool* flag; } extensions[] = {
{ "VK_KHR_portability_enumeration", true, &state.supports.portability },
{ "VK_EXT_debug_utils", config->debug, &state.supports.debug },
{ 0 }, // extra extensions for GLFW
{ 0 }
};
const char* enabledExtensions[32];
uint32_t enabledExtensionCount = 0;
if (state.config.vk.getInstanceExtensions) {
const char** instanceExtensions = state.config.vk.getInstanceExtensions(&enabledExtensionCount);
CHECK(enabledExtensionCount < COUNTOF(enabledExtensions), "Too many instance extensions") return gpu_destroy(), false;
for (uint32_t i = 0; i < enabledExtensionCount; i++) {
enabledExtensions[i] = instanceExtensions[i];
}
}
VkExtensionProperties extensionInfo[256];
count = COUNTOF(extensionInfo);
VK(vkEnumerateInstanceExtensionProperties(NULL, &count, extensionInfo), "Failed to enumerate instance extensions") return gpu_destroy(), false;
const char* enabledExtensions[COUNTOF(extensions)];
for (uint32_t i = 0; i < COUNTOF(extensions); i++) {
if (!extensions[i].shouldEnable) continue;
if (hasExtension(extensionInfo, count, extensions[i].name)) {
if (hasExtension(extensionInfo, extensionCount, extensions[i].name)) {
CHECK(enabledExtensionCount < COUNTOF(enabledExtensions), "Too many instance extensions") return gpu_destroy(), false;
if (extensions[i].isEnabled) *extensions[i].isEnabled = true;
if (extensions[i].flag) *extensions[i].flag = true;
enabledExtensions[enabledExtensionCount++] = extensions[i].name;
} else if (!extensions[i].flag) {
vcheck(VK_ERROR_EXTENSION_NOT_PRESENT, extensions[i].name);
}
}
if (state.config.debug && !supports.validation && state.config.callback) {
state.config.callback(state.config.userdata, "Warning: GPU debug mode is enabled, but validation layer is not supported", false);
// Extra extensions (from GLFW)
if (state.config.vk.getInstanceExtensions) {
uint32_t extraExtensionCount = 0;
const char** extraExtensions = state.config.vk.getInstanceExtensions(&extraExtensionCount);
CHECK(enabledExtensionCount + extraExtensionCount <= COUNTOF(enabledExtensions), "Too many instance extensions") return gpu_destroy(), false;
for (uint32_t i = 0; i < extraExtensionCount; i++) {
enabledExtensions[enabledExtensionCount++] = extraExtensions[i];
}
}
if (state.config.debug && !supports.debug) {
state.config.debug = false;
}
// Instance
VkInstanceCreateInfo instanceInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
#ifdef VK_KHR_portability_enumeration
.flags = supports.portability ? VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR : 0,
#endif
.flags = state.supports.portability ? VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR : 0,
.pApplicationInfo = &(VkApplicationInfo) {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pEngineName = config->engineName,
@ -1935,15 +1933,23 @@ bool gpu_init(gpu_config* config) {
GPU_FOREACH_INSTANCE(GPU_LOAD_INSTANCE);
if (state.config.debug) {
VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
.pfnUserCallback = relay
};
if (state.config.debug && state.config.callback) {
if (state.supports.debug) {
VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
.pfnUserCallback = relay
};
VK(vkCreateDebugUtilsMessengerEXT(state.instance, &messengerInfo, NULL, &state.messenger), "Debug hook setup failed") return gpu_destroy(), false;
VK(vkCreateDebugUtilsMessengerEXT(state.instance, &messengerInfo, NULL, &state.messenger), "Debug hook setup failed") return gpu_destroy(), false;
if (!state.supports.validation) {
state.config.callback(state.config.userdata, "Warning: GPU debugging is enabled, but validation layer is not installed", false);
}
} else {
state.config.callback(state.config.userdata, "Warning: GPU debugging is enabled, but debug extension is not supported", false);
}
}
}
@ -2096,33 +2102,28 @@ bool gpu_init(gpu_config* config) {
}
CHECK(state.queueFamilyIndex != ~0u, "Queue selection failed") return gpu_destroy(), false;
struct {
bool swapchain;
} supports = { 0 };
struct { const char* name; bool shouldEnable; bool* isEnabled; } extensions[] = {
{ "VK_KHR_swapchain", state.surface, &supports.swapchain },
{ "VK_KHR_portability_subset", true, NULL }
struct { const char* name; bool shouldEnable; bool* flag; } extensions[] = {
{ "VK_KHR_swapchain", state.surface, NULL },
{ "VK_KHR_portability_subset", true, &state.supports.portability }
};
const char* enabledExtensions[4];
uint32_t enabledExtensionCount = 0;
VkExtensionProperties extensionInfo[256];
uint32_t count = COUNTOF(extensionInfo);
VK(vkEnumerateDeviceExtensionProperties(state.adapter, NULL, &count, extensionInfo), "Failed to enumerate device extensions") return gpu_destroy(), false;
uint32_t extensionCount = COUNTOF(extensionInfo);
VK(vkEnumerateDeviceExtensionProperties(state.adapter, NULL, &extensionCount, extensionInfo), "Failed to enumerate device extensions") return gpu_destroy(), false;
uint32_t enabledExtensionCount = 0;
const char* enabledExtensions[COUNTOF(extensions)];
for (uint32_t i = 0; i < COUNTOF(extensions); i++) {
if (!extensions[i].shouldEnable) continue;
if (hasExtension(extensionInfo, count, extensions[i].name)) {
if (hasExtension(extensionInfo, extensionCount, extensions[i].name)) {
CHECK(enabledExtensionCount < COUNTOF(enabledExtensions), "Too many device extensions") return gpu_destroy(), false;
if (extensions[i].isEnabled) *extensions[i].isEnabled = true;
if (extensions[i].flag) *extensions[i].flag = true;
enabledExtensions[enabledExtensionCount++] = extensions[i].name;
} else if (!extensions[i].flag) {
vcheck(VK_ERROR_EXTENSION_NOT_PRESENT, extensions[i].name);
}
}
CHECK(supports.swapchain || !state.surface, "Swapchain extension not supported") return gpu_destroy(), false;
VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = config->features ? &enabledFeatures : NULL,
@ -2142,6 +2143,7 @@ bool gpu_init(gpu_config* config) {
} else {
VK(vkCreateDevice(state.adapter, &deviceInfo, NULL, &state.device), "Device creation failed") return gpu_destroy(), false;
}
vkGetDeviceQueue(state.device, state.queueFamilyIndex, 0, &state.queue);
GPU_FOREACH_DEVICE(GPU_LOAD_DEVICE);
}
@ -3046,14 +3048,12 @@ static VkAccessFlags convertCache(gpu_cache cache) {
}
static VkBool32 relay(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, const VkDebugUtilsMessengerCallbackDataEXT* data, void* userdata) {
if (state.config.callback) {
state.config.callback(state.config.userdata, data->pMessage, false);
}
state.config.callback(state.config.userdata, data->pMessage, false);
return VK_FALSE;
}
static void nickname(void* handle, VkObjectType type, const char* name) {
if (name && state.config.debug) {
if (name && state.supports.debug) {
union { uint64_t u64; void* p; } pointer = { .p = handle };
VkDebugUtilsObjectNameInfoEXT info = {

View File

@ -138,7 +138,7 @@ static bool loadOgg(Sound* sound, Blob* blob, bool decode) {
void* data = calloc(1, size);
lovrAssert(data, "Out of memory");
sound->blob = lovrBlobCreate(data, size, "Sound");
if (stb_vorbis_get_samples_float_interleaved(sound->decoder, channels, data, size / sizeof(float)) < (int) sound->frames) {
if (stb_vorbis_get_samples_float_interleaved(sound->decoder, channels, data, (int) size / sizeof(float)) < (int) sound->frames) {
lovrThrow("Could not decode vorbis from '%s'", blob->name);
}
stb_vorbis_close(sound->decoder);

View File

@ -1519,7 +1519,6 @@ ShaderSource lovrGraphicsCompileShader(ShaderStage stage, ShaderSource* source)
int options = 0;
options |= GLSLANG_SHADER_AUTO_MAP_BINDINGS;
options |= GLSLANG_SHADER_AUTO_MAP_LOCATIONS;
glslang_shader_set_options(shader, options);
@ -1714,6 +1713,8 @@ Shader* lovrShaderCreate(const ShaderInfo* info) {
lovrAssert(shader->constants && shader->resources && shader->attributes, "Out of memory");
lovrAssert(shader->flags && shader->flagLookup, "Out of memory");
lovrCheck(shader->constantSize <= state.limits.pushConstantSize, "Shader push constants block is too big");
// Push constants
for (uint32_t i = 0; i < spv[constantStage].pushConstantCount; i++) {
static const FieldType constantTypes[] = {
@ -4935,6 +4936,10 @@ void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t se
.index.count = indexCount
});
if (!vertices) {
return;
}
// T and P stand for toroidal and poloidal, or theta and phi
float dt = (2.f * (float) M_PI) / segmentsT;
float dp = (2.f * (float) M_PI) / segmentsP;

View File

@ -17,19 +17,19 @@ static void evaluate(float* restrict P, size_t n, float t, vec3 p) {
p[2] = P[2] + (P[6] - P[2]) * t;
p[3] = P[3] + (P[7] - P[3]) * t;
} else if (n == 3) {
float t1 = (1 - t);
float t1 = (1.f - t);
float a = t1 * t1;
float b = 2 * t1 * t;
float b = 2.f * t1 * t;
float c = t * t;
p[0] = a * P[0] + b * P[4] + c * P[8];
p[1] = a * P[1] + b * P[5] + c * P[9];
p[2] = a * P[2] + b * P[6] + c * P[10];
p[3] = a * P[3] + b * P[7] + c * P[11];
} else if (n == 4) {
float t1 = (1 - t);
float t1 = (1.f - t);
float a = t1 * t1 * t1;
float b = 3 * t1 * t1 * t;
float c = 3 * t1 * t * t;
float b = 3.f * t1 * t1 * t;
float c = 3.f * t1 * t * t;
float d = t * t * t;
p[0] = a * P[0] + b * P[4] + c * P[8] + d * P[12];
p[1] = a * P[1] + b * P[5] + c * P[9] + d * P[13];
@ -39,7 +39,7 @@ static void evaluate(float* restrict P, size_t n, float t, vec3 p) {
float b = 1.f;
p[0] = p[1] = p[2] = p[3] = 0.f;
for (size_t i = 0; i < n; i++, b *= (float) (n - i) / i) {
float c1 = powf(1 - t, n - (i + 1));
float c1 = powf(1.f - t, n - (i + 1));
float c2 = powf(t, i);
p[0] += b * c1 * c2 * P[i * 4 + 0];
p[1] += b * c1 * c2 * P[i * 4 + 1];