mirror of https://github.com/bjornbytes/lovr.git
Compare commits
15 Commits
16860e8ef5
...
dd4fa5c382
Author | SHA1 | Date |
---|---|---|
bjorn | dd4fa5c382 | |
bjorn | 6011e61d52 | |
bjorn | dd40e6c829 | |
bjorn | b60a9b7b40 | |
bjorn | ed59eeb11c | |
bjorn | ff0d397146 | |
bjorn | 73f61b35b3 | |
bjorn | 2a3215fa05 | |
bjorn | fcbeccdfb1 | |
bjorn | cb59f64a7b | |
bjorn | 804a1e6844 | |
bjorn | a23f0351cc | |
bjorn | 7ceefcf4c2 | |
bjorn | 019814e2c1 | |
bjorn | aa4fce2842 |
|
@ -497,7 +497,7 @@ if target == 'android' then
|
|||
apk = 'bin/lovr.apk'
|
||||
|
||||
manifest = config.android.manifest or ('etc/AndroidManifest_%s.xml'):format(config.android.flavor)
|
||||
package = #config.android.package > 0 and ('--rename-manifest-package ' .. config.android.package) or ''
|
||||
package = config.android.package and #config.android.package > 0 and ('--rename-manifest-package ' .. config.android.package) or ''
|
||||
project = config.android.project and #config.android.project > 0 and ('-A ' .. config.android.project) or ''
|
||||
|
||||
version = config.android.version
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3c132259fa0a151e60a558e81a5bf27b10e167e5
|
||||
Subproject commit de4daf201a2acd83ad523b4c6148e4d8e5b7dab4
|
16
etc/boot.lua
16
etc/boot.lua
|
@ -163,7 +163,6 @@ function lovr.errhand(message, traceback)
|
|||
print('Error:\n' .. message)
|
||||
if not lovr.graphics then return function() return 1 end end
|
||||
|
||||
lovr.graphics.submit()
|
||||
lovr.graphics.setBackground(.11, .10, .14)
|
||||
|
||||
local scale = .3
|
||||
|
@ -194,21 +193,15 @@ function lovr.errhand(message, traceback)
|
|||
local passes = {}
|
||||
if lovr.headset then
|
||||
lovr.headset.update()
|
||||
local texture = lovr.headset.getTexture()
|
||||
if texture then
|
||||
local pass = lovr.graphics.getPass('render', texture)
|
||||
local near, far = lovr.headset.getClipDistance()
|
||||
for i = 1, lovr.headset.getViewCount() do
|
||||
pass:setViewPose(i, lovr.headset.getViewPose(i))
|
||||
local left, right, up, down = lovr.headset.getViewAngles(i)
|
||||
pass:setProjection(i, left, right, up, down, near, far)
|
||||
end
|
||||
local pass = lovr.headset.getPass()
|
||||
if pass then
|
||||
render(pass)
|
||||
passes[#passes + 1] = pass
|
||||
end
|
||||
end
|
||||
if lovr.system.isWindowOpen() then
|
||||
local pass = lovr.graphics.getPass('render', 'window')
|
||||
local pass = lovr.graphics.getWindowPass()
|
||||
pass:reset()
|
||||
local width, height = lovr.system.getWindowDimensions()
|
||||
local projection = lovr.math.mat4():perspective(1.0, width / height, .1, 100)
|
||||
pass:setProjection(1, projection)
|
||||
|
@ -216,6 +209,7 @@ function lovr.errhand(message, traceback)
|
|||
passes[#passes + 1] = pass
|
||||
end
|
||||
lovr.graphics.submit(passes)
|
||||
if lovr.headset then lovr.headset.submit() end
|
||||
if lovr.math then lovr.math.drain() end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ function lovr.load()
|
|||
return
|
||||
end
|
||||
|
||||
lovr.graphics.getWindowPass():setClear(0x20232c)
|
||||
lovr.graphics.setBackground(0x20232c)
|
||||
|
||||
--[=[
|
||||
logo = lovr.graphics.newShader([[
|
||||
|
|
|
@ -8,6 +8,6 @@ layout(set = 1, binding = 1) uniform texture2DArray ArrayTexture;
|
|||
|
||||
vec4 lovrmain() {
|
||||
vec2 uv = vec2(2 * UV.x, UV.y);
|
||||
vec3 uvw = vec3(uv, round(uv.x));
|
||||
vec3 uvw = vec3(uv, round(UV.x));
|
||||
return Color * getPixel(ArrayTexture, uvw);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,17 @@ LOVR_EXPORT int luaopen_lovr_system(lua_State* L);
|
|||
LOVR_EXPORT int luaopen_lovr_thread(lua_State* L);
|
||||
LOVR_EXPORT int luaopen_lovr_timer(lua_State* L);
|
||||
|
||||
void lovrAudioDestroy(void);
|
||||
void lovrEventDestroy(void);
|
||||
void lovrFilesystemDestroy(void);
|
||||
void lovrGraphicsDestroy(void);
|
||||
void lovrHeadsetDestroy(void);
|
||||
void lovrMathDestroy(void);
|
||||
void lovrPhysicsDestroy(void);
|
||||
void lovrSystemDestroy(void);
|
||||
void lovrThreadModuleDestroy(void);
|
||||
void lovrTimerDestroy(void);
|
||||
|
||||
// Object names are lightuserdata because Variants need a non-Lua string due to threads.
|
||||
static int luax_meta__tostring(lua_State* L) {
|
||||
lua_getfield(L, -1, "__info");
|
||||
|
@ -60,12 +71,12 @@ static int luax_meta__gc(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int luax_module__gc(lua_State* L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrmodules");
|
||||
static int luax_runfinalizers(lua_State* L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrfinalizers");
|
||||
for (int i = luax_len(L, 2); i >= 1; i--) {
|
||||
lua_rawgeti(L, 2, i);
|
||||
voidFn* destructor = (voidFn*) lua_tocfunction(L, -1);
|
||||
destructor();
|
||||
voidFn* finalizer = (voidFn*) lua_tocfunction(L, -1);
|
||||
finalizer();
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return 0;
|
||||
|
@ -116,6 +127,40 @@ void luax_preload(lua_State* L) {
|
|||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
// Destroys modules in a specific order
|
||||
void luax_unload(lua_State* L) {
|
||||
#ifndef LOVR_DISABLE_TIMER
|
||||
lovrTimerDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_MATH
|
||||
lovrMathDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_EVENT
|
||||
lovrEventDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_THREAD
|
||||
lovrThreadModuleDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_PHYSICS
|
||||
lovrPhysicsDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_AUDIO
|
||||
lovrAudioDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_HEADSET
|
||||
lovrHeadsetDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_GRAPHICS
|
||||
lovrGraphicsDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_SYSTEM
|
||||
lovrSystemDestroy();
|
||||
#endif
|
||||
#ifndef LOVR_DISABLE_FILESYSTEM
|
||||
lovrFilesystemDestroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions, destructorFn* destructor) {
|
||||
|
||||
// Push metatable
|
||||
|
@ -362,8 +407,8 @@ void luax_setmainthread(lua_State *L) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void luax_atexit(lua_State* L, voidFn* destructor) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrmodules");
|
||||
void luax_atexit(lua_State* L, voidFn* finalizer) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrfinalizers");
|
||||
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_newtable(L);
|
||||
|
@ -372,18 +417,18 @@ void luax_atexit(lua_State* L, voidFn* destructor) {
|
|||
// Userdata sentinel since tables don't have __gc (yet)
|
||||
lua_newuserdata(L, sizeof(void*));
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushcfunction(L, luax_module__gc);
|
||||
lua_pushcfunction(L, luax_runfinalizers);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setfield(L, -2, "");
|
||||
|
||||
// Write to the registry
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "_lovrmodules");
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "_lovrfinalizers");
|
||||
}
|
||||
|
||||
int length = luax_len(L, -1);
|
||||
lua_pushcfunction(L, (lua_CFunction) destructor);
|
||||
lua_pushcfunction(L, (lua_CFunction) finalizer);
|
||||
lua_rawseti(L, -2, length + 1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ typedef struct {
|
|||
#define luax_clearerror(L) lua_pushnil(L), luax_seterror(L)
|
||||
|
||||
void luax_preload(struct lua_State* L);
|
||||
void luax_unload(struct lua_State* L);
|
||||
void _luax_registertype(struct lua_State* L, const char* name, const struct luaL_Reg* functions, void (*destructor)(void*));
|
||||
void* _luax_totype(struct lua_State* L, int index, uint64_t hash);
|
||||
void* _luax_checktype(struct lua_State* L, int index, uint64_t hash, const char* debug);
|
||||
|
@ -126,7 +127,7 @@ int luax_getstack(struct lua_State* L);
|
|||
void luax_pushconf(struct lua_State* L);
|
||||
int luax_setconf(struct lua_State* L);
|
||||
void luax_setmainthread(struct lua_State* L);
|
||||
void luax_atexit(struct lua_State* L, void (*destructor)(void));
|
||||
void luax_atexit(struct lua_State* L, void (*finalizer)(void));
|
||||
uint32_t _luax_checku32(struct lua_State* L, int index);
|
||||
uint32_t _luax_optu32(struct lua_State* L, int index, uint32_t fallback);
|
||||
void luax_readcolor(struct lua_State* L, int index, float color[4]);
|
||||
|
|
|
@ -331,7 +331,6 @@ int luaopen_lovr_audio(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
|
||||
if (lovrAudioInit(spatializer, sampleRate)) {
|
||||
luax_atexit(L, lovrAudioDestroy);
|
||||
if (start) {
|
||||
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
|
||||
lovrAudioStart(AUDIO_PLAYBACK);
|
||||
|
|
|
@ -214,9 +214,6 @@ int luaopen_lovr_event(lua_State* L) {
|
|||
lua_pushcfunction(L, nextEvent);
|
||||
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
if (lovrEventInit()) {
|
||||
luax_atexit(L, lovrEventDestroy);
|
||||
}
|
||||
|
||||
lovrEventInit();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -516,9 +516,7 @@ int luaopen_lovr_filesystem(lua_State* L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (lovrFilesystemInit(archive)) {
|
||||
luax_atexit(L, lovrFilesystemDestroy);
|
||||
}
|
||||
lovrFilesystemInit(archive);
|
||||
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrFilesystem);
|
||||
|
|
|
@ -658,17 +658,10 @@ static int l_lovrGraphicsInit(lua_State* L) {
|
|||
|
||||
if (shaderCache) {
|
||||
config.cacheData = luax_readfile(".lovrshadercache", &config.cacheSize);
|
||||
luax_atexit(L, luax_writeshadercache);
|
||||
}
|
||||
|
||||
if (lovrGraphicsInit(&config)) {
|
||||
luax_atexit(L, lovrGraphicsDestroy);
|
||||
|
||||
// Finalizers run in the opposite order they were added, so this has to go last
|
||||
if (shaderCache) {
|
||||
luax_atexit(L, luax_writeshadercache);
|
||||
}
|
||||
}
|
||||
|
||||
lovrGraphicsInit(&config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -812,6 +805,23 @@ static int l_lovrGraphicsIsFormatSupported(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsGetBackground(lua_State* L) {
|
||||
float color[4];
|
||||
lovrGraphicsGetBackground(color);
|
||||
lua_pushnumber(L, color[0]);
|
||||
lua_pushnumber(L, color[1]);
|
||||
lua_pushnumber(L, color[2]);
|
||||
lua_pushnumber(L, color[3]);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsSetBackground(lua_State* L) {
|
||||
float color[4];
|
||||
luax_readcolor(L, 1, color);
|
||||
lovrGraphicsSetBackground(color);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsGetWindowPass(lua_State* L) {
|
||||
Pass* pass = lovrGraphicsGetWindowPass();
|
||||
luax_pushtype(L, Pass, pass);
|
||||
|
@ -1488,6 +1498,8 @@ static const luaL_Reg lovrGraphics[] = {
|
|||
{ "getFeatures", l_lovrGraphicsGetFeatures },
|
||||
{ "getLimits", l_lovrGraphicsGetLimits },
|
||||
{ "isFormatSupported", l_lovrGraphicsIsFormatSupported },
|
||||
{ "getBackground", l_lovrGraphicsGetBackground },
|
||||
{ "setBackground", l_lovrGraphicsSetBackground },
|
||||
{ "getWindowPass", l_lovrGraphicsGetWindowPass },
|
||||
{ "getDefaultFont", l_lovrGraphicsGetDefaultFont },
|
||||
{ "getBuffer", l_lovrGraphicsGetBuffer },
|
||||
|
|
|
@ -823,24 +823,20 @@ static int l_lovrPassMesh(lua_State* L) {
|
|||
Pass* pass = luax_checktype(L, 1, Pass);
|
||||
Buffer* vertices = !lua_toboolean(L, 2) ? NULL : luax_checktype(L, 2, Buffer);
|
||||
Buffer* indices = luax_totype(L, 3, Buffer);
|
||||
float transform[16];
|
||||
int index = luax_readmat4(L, indices ? 4 : 3, transform, 1);
|
||||
uint32_t start = luax_optu32(L, index++, 1) - 1;
|
||||
uint32_t count = luax_optu32(L, index++, ~0u);
|
||||
uint32_t instances = luax_optu32(L, index, 1);
|
||||
lovrPassMesh(pass, vertices, indices, transform, start, count, instances);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrPassMultimesh(lua_State* L) {
|
||||
Pass* pass = luax_checktype(L, 1, Pass);
|
||||
Buffer* vertices = !lua_toboolean(L, 2) ? NULL : luax_totype(L, 2, Buffer);
|
||||
Buffer* indices = luax_totype(L, 3, Buffer);
|
||||
Buffer* draws = luax_checktype(L, 4, Buffer);
|
||||
uint32_t count = luax_optu32(L, 5, 1);
|
||||
uint32_t offset = luax_optu32(L, 6, 0);
|
||||
uint32_t stride = luax_optu32(L, 7, 0);
|
||||
lovrPassMultimesh(pass, vertices, indices, draws, count, offset, stride);
|
||||
Buffer* indirect = luax_totype(L, 4, Buffer);
|
||||
if (indirect) {
|
||||
uint32_t count = luax_optu32(L, 5, 1);
|
||||
uint32_t offset = luax_optu32(L, 6, 0);
|
||||
uint32_t stride = luax_optu32(L, 7, 0);
|
||||
lovrPassMeshIndirect(pass, vertices, indices, indirect, count, offset, stride);
|
||||
} else {
|
||||
float transform[16];
|
||||
int index = luax_readmat4(L, indices ? 4 : 3, transform, 1);
|
||||
uint32_t start = luax_optu32(L, index++, 1) - 1;
|
||||
uint32_t count = luax_optu32(L, index++, ~0u);
|
||||
uint32_t instances = luax_optu32(L, index, 1);
|
||||
lovrPassMesh(pass, vertices, indices, transform, start, count, instances);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1164,7 +1160,6 @@ const luaL_Reg lovrPass[] = {
|
|||
{ "monkey", l_lovrPassMonkey },
|
||||
{ "draw", l_lovrPassDraw },
|
||||
{ "mesh", l_lovrPassMesh },
|
||||
{ "multimesh", l_lovrPassMultimesh },
|
||||
|
||||
{ "compute", l_lovrPassCompute },
|
||||
|
||||
|
|
|
@ -488,12 +488,37 @@ static int l_lovrHeadsetVibrate(lua_State* L) {
|
|||
}
|
||||
|
||||
static int l_lovrHeadsetNewModel(lua_State* L) {
|
||||
lua_pushnil(L); // TODO
|
||||
return 1;
|
||||
Device device = luax_optdevice(L, 1);
|
||||
bool animated = false;
|
||||
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_getfield(L, 2, "animated");
|
||||
animated = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
ModelData* modelData = lovrHeadsetInterface->newModelData(device, animated);
|
||||
|
||||
if (modelData) {
|
||||
ModelInfo info = { .data = modelData, .mipmaps = true };
|
||||
Model* model = lovrModelCreate(&info);
|
||||
luax_pushtype(L, Model, model);
|
||||
lovrRelease(modelData, lovrModelDataDestroy);
|
||||
lovrRelease(model, lovrModelDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrHeadsetAnimate(lua_State* L) {
|
||||
lua_pushboolean(L, false); // TODO
|
||||
Device device = luax_optdevice(L, 1);
|
||||
Model* model = luax_checktype(L, 2, Model);
|
||||
if (lovrHeadsetInterface->animate(device, model)) {
|
||||
lua_pushboolean(L, true);
|
||||
return 1;
|
||||
}
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -672,7 +697,6 @@ int luaopen_lovr_headset(lua_State* L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_atexit(L, lovrHeadsetDestroy);
|
||||
lovrHeadsetInit(&config);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -389,9 +389,7 @@ int luaopen_lovr_math(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
|
||||
// Module
|
||||
if (lovrMathInit()) {
|
||||
luax_atexit(L, lovrMathDestroy);
|
||||
}
|
||||
lovrMathInit();
|
||||
|
||||
// Each Lua state gets its own thread-local Pool
|
||||
pool = lovrPoolCreate();
|
||||
|
|
|
@ -169,8 +169,6 @@ int luaopen_lovr_physics(lua_State* L) {
|
|||
luax_registertype(L, CapsuleShape);
|
||||
luax_registertype(L, CylinderShape);
|
||||
luax_registertype(L, MeshShape);
|
||||
if (lovrPhysicsInit()) {
|
||||
luax_atexit(L, lovrPhysicsDestroy);
|
||||
}
|
||||
lovrPhysicsInit();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -205,8 +205,6 @@ static const luaL_Reg lovrSystem[] = {
|
|||
int luaopen_lovr_system(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrSystem);
|
||||
if (lovrSystemInit()) {
|
||||
luax_atexit(L, lovrSystemDestroy);
|
||||
}
|
||||
lovrSystemInit();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -110,8 +110,6 @@ int luaopen_lovr_thread(lua_State* L) {
|
|||
luax_register(L, lovrThreadModule);
|
||||
luax_registertype(L, Thread);
|
||||
luax_registertype(L, Channel);
|
||||
if (lovrThreadModuleInit()) {
|
||||
luax_atexit(L, lovrThreadModuleDestroy);
|
||||
}
|
||||
lovrThreadModuleInit();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ static const luaL_Reg lovrTimer[] = {
|
|||
int luaopen_lovr_timer(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrTimer);
|
||||
if (lovrTimerInit()) {
|
||||
luax_atexit(L, lovrTimerDestroy);
|
||||
}
|
||||
lovrTimerInit();
|
||||
luax_atexit(L, lovrTimerDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -143,6 +143,8 @@ bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info);
|
|||
bool gpu_texture_init_view(gpu_texture* texture, gpu_texture_view_info* info);
|
||||
void gpu_texture_destroy(gpu_texture* texture);
|
||||
gpu_texture* gpu_surface_acquire(void);
|
||||
void gpu_xr_acquire(gpu_stream* stream, gpu_texture* texture);
|
||||
void gpu_xr_release(gpu_stream* stream, gpu_texture* texture);
|
||||
|
||||
// Sampler
|
||||
|
||||
|
|
|
@ -706,6 +706,56 @@ gpu_texture* gpu_surface_acquire(void) {
|
|||
return &state.surfaceTextures[state.currentSurfaceTexture];
|
||||
}
|
||||
|
||||
void gpu_xr_acquire(gpu_stream* stream, gpu_texture* texture) {
|
||||
if (texture->layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { // TODO depth
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier transition = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = 0,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = texture->layout,
|
||||
.image = texture->handle,
|
||||
.subresourceRange.aspectMask = texture->aspect,
|
||||
.subresourceRange.baseMipLevel = 0,
|
||||
.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.subresourceRange.baseArrayLayer = 0,
|
||||
.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS
|
||||
};
|
||||
|
||||
VkPipelineStageFlags prev = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
VkPipelineStageFlags next = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
|
||||
vkCmdPipelineBarrier(stream->commands, prev, next, 0, 0, NULL, 0, NULL, 1, &transition);
|
||||
}
|
||||
|
||||
void gpu_xr_release(gpu_stream* stream, gpu_texture* texture) {
|
||||
if (texture->layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { // TODO depth
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier transition = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
.dstAccessMask = 0,
|
||||
.oldLayout = texture->layout,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.image = texture->handle,
|
||||
.subresourceRange.aspectMask = texture->aspect,
|
||||
.subresourceRange.baseMipLevel = 0,
|
||||
.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.subresourceRange.baseArrayLayer = 0,
|
||||
.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS
|
||||
};
|
||||
|
||||
VkPipelineStageFlags prev = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkPipelineStageFlags next = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
|
||||
vkCmdPipelineBarrier(stream->commands, prev, next, 0, 0, NULL, 0, NULL, 1, &transition);
|
||||
}
|
||||
|
||||
// Sampler
|
||||
|
||||
bool gpu_sampler_init(gpu_sampler* sampler, gpu_sampler_info* info) {
|
||||
|
@ -2249,9 +2299,12 @@ bool gpu_init(gpu_config* config) {
|
|||
.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
|
||||
};
|
||||
|
||||
if (config->vk.cacheSize >= sizeof(VkPipelineCacheHeaderVersionOne)) {
|
||||
VkPipelineCacheHeaderVersionOne* header = config->vk.cacheData;
|
||||
if (header->headerSize == sizeof(*header) && header->headerVersion == VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {
|
||||
// Not using VkPipelineCacheHeaderVersionOne since it's missing from Android headers
|
||||
if (config->vk.cacheSize >= 16 + VK_UUID_SIZE) {
|
||||
uint32_t headerSize, headerVersion;
|
||||
memcpy(&headerSize, config->vk.cacheData, 4);
|
||||
memcpy(&headerVersion, (char*) config->vk.cacheData + 4, 4);
|
||||
if (headerSize == 16 + VK_UUID_SIZE && headerVersion == VK_PIPELINE_CACHE_HEADER_VERSION_ONE) {
|
||||
cacheInfo.initialDataSize = config->vk.cacheSize;
|
||||
cacheInfo.pInitialData = config->vk.cacheData;
|
||||
}
|
||||
|
|
|
@ -651,8 +651,8 @@ MAF void mat4_getFov(mat4 m, float* left, float* right, float* up, float* down)
|
|||
float v[4][4] = {
|
||||
{ 1.f, 0.f, 0.f, 1.f },
|
||||
{ -1.f, 0.f, 0.f, 1.f },
|
||||
{ 0.f, -1.f, 0.f, 1.f },
|
||||
{ 0.f, 1.f, 0.f, 1.f }
|
||||
{ 0.f, 1.f, 0.f, 1.f },
|
||||
{ 0.f, -1.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
float transpose[16];
|
||||
|
|
|
@ -132,6 +132,7 @@ int main(int argc, char** argv) {
|
|||
memset(&cookie.value, 0, sizeof(cookie.value));
|
||||
}
|
||||
lua_close(L);
|
||||
luax_unload(L);
|
||||
} while (restart);
|
||||
|
||||
os_destroy();
|
||||
|
@ -147,6 +148,7 @@ void lovrDestroy(void* arg) {
|
|||
lua_State* L = context->L;
|
||||
emscripten_cancel_main_loop();
|
||||
lua_close(L);
|
||||
luax_unload(L);
|
||||
os_destroy();
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +167,7 @@ static void emscriptenLoop(void* arg) {
|
|||
}
|
||||
|
||||
lua_close(context->L);
|
||||
luax_unload(L);
|
||||
emscripten_cancel_main_loop();
|
||||
|
||||
if (restart) {
|
||||
|
|
|
@ -29,65 +29,9 @@ ModelData* lovrModelDataCreate(Blob* source, ModelDataIO* io) {
|
|||
}
|
||||
}
|
||||
|
||||
// Precomputed properties and validation
|
||||
lovrModelDataFinalize(model);
|
||||
|
||||
for (uint32_t i = 0; i < model->primitiveCount; i++) {
|
||||
model->primitives[i].skin = 0xaaaaaaaa;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
ModelNode* node = &model->nodes[i];
|
||||
for (uint32_t j = 0, index = node->primitiveIndex; j < node->primitiveCount; j++, index++) {
|
||||
if (model->primitives[index].skin != 0xaaaaaaaa) {
|
||||
lovrCheck(model->primitives[index].skin == node->skin, "Model has a mesh used with multiple skins, which is not supported");
|
||||
} else {
|
||||
model->primitives[index].skin = node->skin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model->indexType = U16;
|
||||
for (uint32_t i = 0; i < model->primitiveCount; i++) {
|
||||
ModelPrimitive* primitive = &model->primitives[i];
|
||||
|
||||
uint32_t vertexCount = primitive->attributes[ATTR_POSITION]->count;
|
||||
if (primitive->skin != ~0u) {
|
||||
model->skins[primitive->skin].vertexCount += vertexCount;
|
||||
model->skinnedVertexCount += vertexCount;
|
||||
}
|
||||
model->vertexCount += vertexCount;
|
||||
|
||||
model->indexCount += primitive->indices ? primitive->indices->count : 0;
|
||||
if (primitive->indices) {
|
||||
if (primitive->indices->type == U32) {
|
||||
primitive->indices->stride = 4;
|
||||
model->indexType = U32;
|
||||
} else {
|
||||
primitive->indices->stride = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < MAX_DEFAULT_ATTRIBUTES; i++) {
|
||||
ModelAttribute* attribute = primitive->attributes[i];
|
||||
if (attribute) {
|
||||
attribute->stride = model->buffers[attribute->buffer].stride;
|
||||
if (attribute->stride == 0) {
|
||||
attribute->stride = typeSizes[attribute->type] * attribute->components;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
model->nodes[i].parent = ~0u;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
ModelNode* node = &model->nodes[i];
|
||||
for (uint32_t j = 0; j < node->childCount; j++) {
|
||||
model->nodes[node->children[j]].parent = i;
|
||||
}
|
||||
}
|
||||
return model;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
@ -151,6 +95,66 @@ void lovrModelDataAllocate(ModelData* model) {
|
|||
map_init(&model->nodeMap, model->nodeCount);
|
||||
}
|
||||
|
||||
void lovrModelDataFinalize(ModelData* model) {
|
||||
for (uint32_t i = 0; i < model->primitiveCount; i++) {
|
||||
model->primitives[i].skin = 0xaaaaaaaa;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
ModelNode* node = &model->nodes[i];
|
||||
for (uint32_t j = 0, index = node->primitiveIndex; j < node->primitiveCount; j++, index++) {
|
||||
if (model->primitives[index].skin != 0xaaaaaaaa) {
|
||||
lovrCheck(model->primitives[index].skin == node->skin, "Model has a mesh used with multiple skins, which is not supported");
|
||||
} else {
|
||||
model->primitives[index].skin = node->skin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model->indexType = U16;
|
||||
for (uint32_t i = 0; i < model->primitiveCount; i++) {
|
||||
ModelPrimitive* primitive = &model->primitives[i];
|
||||
|
||||
uint32_t vertexCount = primitive->attributes[ATTR_POSITION]->count;
|
||||
if (primitive->skin != ~0u) {
|
||||
model->skins[primitive->skin].vertexCount += vertexCount;
|
||||
model->skinnedVertexCount += vertexCount;
|
||||
}
|
||||
model->vertexCount += vertexCount;
|
||||
|
||||
model->indexCount += primitive->indices ? primitive->indices->count : 0;
|
||||
if (primitive->indices) {
|
||||
if (primitive->indices->type == U32) {
|
||||
primitive->indices->stride = 4;
|
||||
model->indexType = U32;
|
||||
} else {
|
||||
primitive->indices->stride = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < MAX_DEFAULT_ATTRIBUTES; i++) {
|
||||
ModelAttribute* attribute = primitive->attributes[i];
|
||||
if (attribute) {
|
||||
attribute->stride = model->buffers[attribute->buffer].stride;
|
||||
if (attribute->stride == 0) {
|
||||
attribute->stride = typeSizes[attribute->type] * attribute->components;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
model->nodes[i].parent = ~0u;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < model->nodeCount; i++) {
|
||||
ModelNode* node = &model->nodes[i];
|
||||
for (uint32_t j = 0; j < node->childCount; j++) {
|
||||
model->nodes[node->children[j]].parent = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrModelDataCopyAttribute(ModelData* data, ModelAttribute* attribute, char* dst, AttributeType type, uint32_t components, bool normalized, uint32_t count, size_t stride, uint8_t clear) {
|
||||
char* src = attribute ? data->buffers[attribute->buffer].data + attribute->offset : NULL;
|
||||
size_t size = components * typeSizes[type];
|
||||
|
@ -195,6 +199,12 @@ void lovrModelDataCopyAttribute(ModelData* data, ModelAttribute* attribute, char
|
|||
((uint8_t*) dst)[j] = (uint8_t) ((uint16_t*) src)[j];
|
||||
}
|
||||
}
|
||||
} else if (attribute->type == I16 && !attribute->normalized && !normalized) {
|
||||
for (uint32_t i = 0; i < count; i++, src += attribute->stride, dst += stride) {
|
||||
for (uint32_t j = 0; j < components; j++) {
|
||||
((uint8_t*) dst)[j] = (uint8_t) ((int16_t*) src)[j];
|
||||
}
|
||||
}
|
||||
} else if (attribute->type == F32 && normalized) {
|
||||
for (uint32_t i = 0; i < count; i++, src += attribute->stride, dst += stride) {
|
||||
for (uint32_t j = 0; j < components; j++) {
|
||||
|
|
|
@ -215,6 +215,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, struct Blob* blob, ModelDataIO
|
|||
ModelData* lovrModelDataInitStl(ModelData* model, struct Blob* blob, ModelDataIO* io);
|
||||
void lovrModelDataDestroy(void* ref);
|
||||
void lovrModelDataAllocate(ModelData* model);
|
||||
void lovrModelDataFinalize(ModelData* model);
|
||||
void lovrModelDataCopyAttribute(ModelData* data, ModelAttribute* attribute, char* dst, AttributeType type, uint32_t components, bool normalized, uint32_t count, size_t stride, uint8_t clear);
|
||||
void lovrModelDataGetBoundingBox(ModelData* data, float box[6]);
|
||||
void lovrModelDataGetBoundingSphere(ModelData* data, float sphere[4]);
|
||||
|
|
|
@ -62,6 +62,7 @@ struct Buffer {
|
|||
|
||||
struct Texture {
|
||||
uint32_t ref;
|
||||
uint32_t xrTick;
|
||||
gpu_texture* gpu;
|
||||
gpu_texture* renderView;
|
||||
Material* material;
|
||||
|
@ -127,6 +128,7 @@ struct Material {
|
|||
uint16_t block;
|
||||
gpu_bundle* bundle;
|
||||
MaterialInfo info;
|
||||
bool hasWritableTexture;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -361,6 +363,7 @@ static struct {
|
|||
gpu_device_info device;
|
||||
gpu_features features;
|
||||
gpu_limits limits;
|
||||
float background[4];
|
||||
Texture* window;
|
||||
Pass* windowPass;
|
||||
Font* defaultFont;
|
||||
|
@ -401,6 +404,7 @@ static void mipmapTexture(gpu_stream* stream, Texture* texture, uint32_t base, u
|
|||
static ShaderResource* findShaderResource(Shader* shader, const char* name, size_t length, uint32_t slot);
|
||||
static void trackBuffer(Pass* pass, Buffer* buffer, gpu_phase phase, gpu_cache cache);
|
||||
static void trackTexture(Pass* pass, Texture* texture, gpu_phase phase, gpu_cache cache);
|
||||
static void trackMaterial(Pass* pass, Material* material, gpu_phase phase, gpu_cache cache);
|
||||
static void updateModelTransforms(Model* model, uint32_t nodeIndex, float* parent);
|
||||
static void checkShaderFeatures(uint32_t* features, uint32_t count);
|
||||
static void onMessage(void* context, const char* message, bool severe);
|
||||
|
@ -753,6 +757,20 @@ void lovrGraphicsGetShaderCache(void* data, size_t* size) {
|
|||
gpu_pipeline_get_cache(data, size);
|
||||
}
|
||||
|
||||
void lovrGraphicsGetBackground(float background[4]) {
|
||||
background[0] = lovrMathLinearToGamma(state.background[0]);
|
||||
background[1] = lovrMathLinearToGamma(state.background[1]);
|
||||
background[2] = lovrMathLinearToGamma(state.background[2]);
|
||||
background[3] = state.background[3];
|
||||
}
|
||||
|
||||
void lovrGraphicsSetBackground(float background[4]) {
|
||||
state.background[0] = lovrMathGammaToLinear(background[0]);
|
||||
state.background[1] = lovrMathGammaToLinear(background[1]);
|
||||
state.background[2] = lovrMathGammaToLinear(background[2]);
|
||||
state.background[3] = background[3];
|
||||
}
|
||||
|
||||
void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
||||
if (!state.active) {
|
||||
return;
|
||||
|
@ -872,8 +890,7 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
|||
// finish. In between, the 'flush' cache is flushed and the 'clear' cache is cleared.
|
||||
gpu_barrier* barrier = &barriers[sync->lastWriteIndex];
|
||||
|
||||
// Only the first write in a pass is considered, because each pass can only perform one type
|
||||
// of write to a resource, and there is not currently any intra-pass synchronization.
|
||||
// Only the first write in a pass is considered for a barrier (and there's no intra-pass sync)
|
||||
if (sync->lastWriteIndex == i + 1) {
|
||||
continue;
|
||||
}
|
||||
|
@ -939,6 +956,16 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
|||
for (uint32_t i = 0; i < count; i++) {
|
||||
for (uint32_t j = 0; j < passes[i]->access.length; j++) {
|
||||
passes[i]->access.data[j].sync->lastWriteIndex = 0;
|
||||
|
||||
// OpenXR swapchain texture layout transitions >__>
|
||||
|
||||
Texture* texture = passes[i]->access.data[j].texture;
|
||||
|
||||
if (texture && texture->info.xr && texture->xrTick != state.tick) {
|
||||
gpu_xr_acquire(streams[0], texture->gpu);
|
||||
gpu_xr_release(streams[total - 1], texture->gpu);
|
||||
texture->xrTick = state.tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1896,6 +1923,7 @@ Material* lovrMaterialCreate(const MaterialInfo* info) {
|
|||
Texture* texture = textures[i] ? textures[i] : state.defaultTexture;
|
||||
lovrCheck(i == 0 || texture->info.type == TEXTURE_2D, "Material textures must be 2D");
|
||||
bindings[i + 1] = (gpu_binding) { i + 1, GPU_SLOT_SAMPLED_TEXTURE, .texture = texture->gpu };
|
||||
material->hasWritableTexture |= texture->info.usage != TEXTURE_SAMPLE;
|
||||
}
|
||||
|
||||
gpu_bundle_info bundleInfo = {
|
||||
|
@ -3399,6 +3427,10 @@ void lovrPassReset(Pass* pass) {
|
|||
} else {
|
||||
pass->target.color[i].texture = lovrGraphicsGetWindowTexture()->gpu;
|
||||
}
|
||||
|
||||
// The window pass always uses the global clear color. The intent is that exposing a global
|
||||
// clear color that applies to the window/headset is more friendly than messing with passes.
|
||||
memcpy(pass->target.color[0].clear, state.background, 4 * sizeof(float));
|
||||
}
|
||||
|
||||
if (canvas->mipmap) {
|
||||
|
@ -4113,10 +4145,12 @@ static void flushBuiltins(Pass* pass, Draw* draw, Shader* shader) {
|
|||
static void flushMaterial(Pass* pass, Draw* draw, Shader* shader) {
|
||||
if (draw->material && draw->material != pass->pipeline->material) {
|
||||
gpu_bind_bundle(pass->stream, shader->gpu, 1, draw->material->bundle, NULL, 0);
|
||||
trackMaterial(pass, draw->material, GPU_PHASE_SHADER_VERTEX | GPU_PHASE_SHADER_FRAGMENT, GPU_CACHE_TEXTURE);
|
||||
pass->materialDirty = true;
|
||||
} else if (pass->materialDirty) {
|
||||
Material* material = pass->pipeline->material ? pass->pipeline->material : state.defaultMaterial;
|
||||
gpu_bind_bundle(pass->stream, shader->gpu, 1, material->bundle, NULL, 0);
|
||||
trackMaterial(pass, material, GPU_PHASE_SHADER_VERTEX | GPU_PHASE_SHADER_FRAGMENT, GPU_CACHE_TEXTURE);
|
||||
pass->materialDirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -5015,13 +5049,13 @@ void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transfor
|
|||
});
|
||||
}
|
||||
|
||||
void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* draws, uint32_t count, uint32_t offset, uint32_t stride) {
|
||||
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* draws, uint32_t count, uint32_t offset, uint32_t stride) {
|
||||
lovrCheck(pass->info.type == PASS_RENDER, "This function can only be called on a render pass");
|
||||
lovrCheck(offset % 4 == 0, "Multimesh draw buffer offset must be a multiple of 4");
|
||||
lovrCheck(offset % 4 == 0, "Buffer offset must be a multiple of 4 when sourcing draws from a Buffer");
|
||||
uint32_t commandSize = indices ? 20 : 16;
|
||||
stride = stride ? stride : commandSize;
|
||||
uint32_t totalSize = stride * (count - 1) + commandSize;
|
||||
lovrCheck(offset + totalSize < draws->size, "Multimesh draw range exceeds size of draw buffer");
|
||||
lovrCheck(offset + totalSize < draws->size, "Draw buffer range exceeds the size of the buffer");
|
||||
|
||||
Draw draw = (Draw) {
|
||||
.mode = pass->pipeline->mode,
|
||||
|
@ -5030,12 +5064,13 @@ void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* dr
|
|||
};
|
||||
|
||||
Shader* shader = pass->pipeline->shader;
|
||||
lovrCheck(shader, "A custom Shader must be bound to draw a multimesh");
|
||||
lovrCheck(shader, "A custom Shader must be bound to source draws from a Buffer");
|
||||
|
||||
flushPipeline(pass, &draw, shader);
|
||||
flushConstants(pass, shader);
|
||||
flushBindings(pass, shader);
|
||||
flushBuiltins(pass, &draw, shader);
|
||||
flushMaterial(pass, &draw, shader);
|
||||
flushBuffers(pass, &draw);
|
||||
|
||||
if (indices) {
|
||||
|
@ -5581,7 +5616,7 @@ static void trackBuffer(Pass* pass, Buffer* buffer, gpu_phase phase, gpu_cache c
|
|||
}
|
||||
|
||||
static void trackTexture(Pass* pass, Texture* texture, gpu_phase phase, gpu_cache cache) {
|
||||
if (texture == state.window) {
|
||||
if (!texture || texture == state.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5604,6 +5639,20 @@ static void trackTexture(Pass* pass, Texture* texture, gpu_phase phase, gpu_cach
|
|||
lovrRetain(texture);
|
||||
}
|
||||
|
||||
static void trackMaterial(Pass* pass, Material* material, gpu_phase phase, gpu_cache cache) {
|
||||
if (!material->hasWritableTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
trackTexture(pass, material->info.texture, phase, cache);
|
||||
trackTexture(pass, material->info.glowTexture, phase, cache);
|
||||
trackTexture(pass, material->info.occlusionTexture, phase, cache);
|
||||
trackTexture(pass, material->info.metalnessTexture, phase, cache);
|
||||
trackTexture(pass, material->info.roughnessTexture, phase, cache);
|
||||
trackTexture(pass, material->info.clearcoatTexture, phase, cache);
|
||||
trackTexture(pass, material->info.normalTexture, phase, cache);
|
||||
}
|
||||
|
||||
static void updateModelTransforms(Model* model, uint32_t nodeIndex, float* parent) {
|
||||
mat4 global = model->globalTransforms + 16 * nodeIndex;
|
||||
NodeTransform* local = &model->localTransforms[nodeIndex];
|
||||
|
|
|
@ -103,6 +103,9 @@ void lovrGraphicsGetLimits(GraphicsLimits* limits);
|
|||
bool lovrGraphicsIsFormatSupported(uint32_t format, uint32_t features);
|
||||
void lovrGraphicsGetShaderCache(void* data, size_t* size);
|
||||
|
||||
void lovrGraphicsGetBackground(float background[4]);
|
||||
void lovrGraphicsSetBackground(float background[4]);
|
||||
|
||||
void lovrGraphicsSubmit(Pass** passes, uint32_t count);
|
||||
void lovrGraphicsPresent(void);
|
||||
void lovrGraphicsWait(void);
|
||||
|
@ -212,6 +215,7 @@ typedef struct {
|
|||
uint32_t samples;
|
||||
uint32_t usage;
|
||||
bool srgb;
|
||||
bool xr;
|
||||
uintptr_t handle;
|
||||
uint32_t imageCount;
|
||||
struct Image** images;
|
||||
|
@ -644,7 +648,7 @@ void lovrPassFill(Pass* pass, Texture* texture);
|
|||
void lovrPassMonkey(Pass* pass, float* transform);
|
||||
void lovrPassDrawModel(Pass* pass, Model* model, float* transform, uint32_t node, bool recurse, uint32_t instances);
|
||||
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances);
|
||||
void lovrPassMultimesh(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride);
|
||||
void lovrPassMeshIndirect(Pass* pass, Buffer* vertices, Buffer* indices, Buffer* indirect, uint32_t count, uint32_t offset, uint32_t stride);
|
||||
|
||||
void lovrPassCompute(Pass* pass, uint32_t x, uint32_t y, uint32_t z, Buffer* indirect, uint32_t offset);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ static bool desktop_getViewAngles(uint32_t view, float* left, float* right, floa
|
|||
uint32_t width, height;
|
||||
desktop_getDisplayDimensions(&width, &height);
|
||||
aspect = (float) width / height;
|
||||
fov = .5f;
|
||||
fov = .7f;
|
||||
*left = atanf(tanf(fov) * aspect);
|
||||
*right = atanf(tanf(fov) * aspect);
|
||||
*up = fov;
|
||||
|
|
|
@ -918,7 +918,8 @@ static void openxr_start(void) {
|
|||
.mipmaps = 1,
|
||||
.samples = 1,
|
||||
.usage = TEXTURE_RENDER | TEXTURE_SAMPLE,
|
||||
.handle = (uintptr_t) images[i].image
|
||||
.handle = (uintptr_t) images[i].image,
|
||||
.xr = true
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -986,7 +987,7 @@ static void openxr_destroy(void) {
|
|||
if (state.actionSet) xrDestroyActionSet(state.actionSet);
|
||||
if (state.swapchain) xrDestroySwapchain(state.swapchain);
|
||||
if (state.referenceSpace) xrDestroySpace(state.referenceSpace);
|
||||
if (state.session) xrEndSession(state.session);
|
||||
if (state.session) xrDestroySession(state.session);
|
||||
if (state.instance) xrDestroyInstance(state.instance);
|
||||
memset(&state, 0, sizeof(state));
|
||||
}
|
||||
|
@ -1429,7 +1430,7 @@ static ModelData* openxr_newModelData(Device device, bool animated) {
|
|||
mesh.vertexBlendWeights = (XrVector4f*) (meshData + offset), offset += sizes[7];
|
||||
mesh.indices = (int16_t*) (meshData + offset), offset += sizes[8];
|
||||
float* inverseBindMatrices = (float*) (meshData + offset); offset += sizes[9];
|
||||
lovrAssert(offset == totalSize, "Unreachable");
|
||||
lovrAssert(offset == totalSize, "Unreachable!");
|
||||
|
||||
result = xrGetHandMeshFB(tracker, &mesh);
|
||||
if (XR_FAILED(result)) {
|
||||
|
@ -1494,7 +1495,7 @@ static ModelData* openxr_newModelData(Device device, bool animated) {
|
|||
.stride = sizeof(mesh.indices[0])
|
||||
};
|
||||
|
||||
model->attributes[0] = (ModelAttribute) { .buffer = 0, .type = F32, .components = 3 };
|
||||
model->attributes[0] = (ModelAttribute) { .buffer = 0, .type = F32, .components = 3, .count = vertexCount };
|
||||
model->attributes[1] = (ModelAttribute) { .buffer = 1, .type = F32, .components = 3 };
|
||||
model->attributes[2] = (ModelAttribute) { .buffer = 2, .type = F32, .components = 2 };
|
||||
model->attributes[3] = (ModelAttribute) { .buffer = 3, .type = I16, .components = 4 };
|
||||
|
@ -1573,6 +1574,8 @@ static ModelData* openxr_newModelData(Device device, bool animated) {
|
|||
*children++ = XR_HAND_JOINT_WRIST_EXT;
|
||||
*children++ = model->jointCount;
|
||||
|
||||
lovrModelDataFinalize(model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -1633,11 +1636,12 @@ static bool openxr_animate(Device device, Model* model) {
|
|||
XR_HAND_JOINT_LITTLE_DISTAL_EXT
|
||||
};
|
||||
|
||||
float scale[4] = { 1.f, 1.f, 1.f, 1.f };
|
||||
|
||||
// The following can be optimized a lot (ideally we would set the global transform for the nodes)
|
||||
for (uint32_t i = 0; i < COUNTOF(joints); i++) {
|
||||
if (jointParents[i] == ~0u) {
|
||||
float position[4] = { 0.f, 0.f, 0.f };
|
||||
float scale[4] = { 1.f, 1.f, 1.f, 1.f };
|
||||
float orientation[4] = { 0.f, 0.f, 0.f, 1.f };
|
||||
lovrModelSetNodeTransform(model, i, position, scale, orientation, 1.f);
|
||||
} else {
|
||||
|
@ -1656,8 +1660,6 @@ static bool openxr_animate(Device device, Model* model) {
|
|||
quat_rotate(orientation, position);
|
||||
quat_mul(orientation, orientation, &pose->orientation.x);
|
||||
|
||||
float scale[4] = { 1.f, 1.f, 1.f, 1.f };
|
||||
|
||||
lovrModelSetNodeTransform(model, i, position, scale, orientation, 1.f);
|
||||
}
|
||||
}
|
||||
|
@ -1666,12 +1668,12 @@ static bool openxr_animate(Device device, Model* model) {
|
|||
}
|
||||
|
||||
static Texture* openxr_getTexture(void) {
|
||||
return state.began && state.frameState.shouldRender ? state.textures[state.textureIndex] : NULL;
|
||||
}
|
||||
if (!SESSION_ACTIVE(state.sessionState)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Pass* openxr_getPass(void) {
|
||||
if (state.began) {
|
||||
return state.frameState.shouldRender ? state.pass : NULL;
|
||||
return state.frameState.shouldRender ? state.textures[state.textureIndex] : NULL;
|
||||
}
|
||||
|
||||
XrFrameBeginInfo beginfo = { .type = XR_TYPE_FRAME_BEGIN_INFO };
|
||||
|
@ -1685,7 +1687,27 @@ static Pass* openxr_getPass(void) {
|
|||
XrSwapchainImageWaitInfo waitInfo = { XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, .timeout = XR_INFINITE_DURATION };
|
||||
XR(xrAcquireSwapchainImage(state.swapchain, NULL, &state.textureIndex));
|
||||
XR(xrWaitSwapchainImage(state.swapchain, &waitInfo));
|
||||
lovrPassSetTarget(state.pass, &state.textures[state.textureIndex], NULL);
|
||||
|
||||
return state.textures[state.textureIndex];
|
||||
}
|
||||
|
||||
static Pass* openxr_getPass(void) {
|
||||
if (state.began) {
|
||||
return state.frameState.shouldRender ? state.pass : NULL;
|
||||
}
|
||||
|
||||
Texture* texture = openxr_getTexture();
|
||||
|
||||
if (!texture) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t stencil;
|
||||
float color[4][4], depth;
|
||||
lovrPassGetClear(state.pass, color, &depth, &stencil);
|
||||
lovrGraphicsGetBackground(color[0]);
|
||||
lovrPassSetClear(state.pass, color, depth, stencil);
|
||||
lovrPassSetTarget(state.pass, &texture, NULL);
|
||||
lovrPassReset(state.pass);
|
||||
|
||||
uint32_t count;
|
||||
|
|
Loading…
Reference in New Issue