mirror of https://github.com/bjornbytes/lovr.git
Compare commits
5 Commits
8af3fffe2f
...
16860e8ef5
Author | SHA1 | Date |
---|---|---|
bjorn | 16860e8ef5 | |
bjorn | 7c7f8ed907 | |
bjorn | eac3299bd0 | |
bjorn | a6d843c642 | |
bjorn | acd87a5e5c |
|
@ -132,6 +132,7 @@ function lovr.run()
|
|||
pass:reset()
|
||||
local skip = lovr.mirror(pass)
|
||||
if not skip then lovr.graphics.submit(pass) end
|
||||
lovr.graphics.present()
|
||||
end
|
||||
end
|
||||
if lovr.headset then lovr.headset.submit() end
|
||||
|
|
|
@ -62,6 +62,18 @@ static ModelAnimation* luax_checkanimation(lua_State* L, int index, ModelData* m
|
|||
}
|
||||
}
|
||||
|
||||
static int l_lovrModelDataGetMetadata(lua_State* L) {
|
||||
ModelData* model = luax_checktype(L, 1, ModelData);
|
||||
|
||||
if (!model->metadata || model->metadataSize == 0) {
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
lua_pushlstring(L, model->metadata, model->metadataSize);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrModelDataGetBlobCount(lua_State* L) {
|
||||
ModelData* model = luax_checktype(L, 1, ModelData);
|
||||
lua_pushinteger(L, model->blobCount);
|
||||
|
@ -731,6 +743,7 @@ static int l_lovrModelDataGetSkinInverseBindMatrix(lua_State* L) {
|
|||
}
|
||||
|
||||
const luaL_Reg lovrModelData[] = {
|
||||
{ "getMetadata", l_lovrModelDataGetMetadata },
|
||||
{ "getBlobCount", l_lovrModelDataGetBlobCount },
|
||||
{ "getBlob", l_lovrModelDataGetBlob },
|
||||
{ "getImageCount", l_lovrModelDataGetImageCount },
|
||||
|
|
|
@ -703,6 +703,11 @@ static int l_lovrGraphicsSubmit(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsPresent(lua_State* L) {
|
||||
lovrGraphicsPresent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsWait(lua_State* L) {
|
||||
lovrGraphicsWait();
|
||||
return 0;
|
||||
|
@ -795,17 +800,6 @@ static int l_lovrGraphicsGetLimits(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsGetStats(lua_State* L) {
|
||||
GraphicsStats stats;
|
||||
lovrGraphicsGetStats(&stats);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushinteger(L, stats.pipelineSwitches), lua_setfield(L, -2, "pipelineSwitches");
|
||||
lua_pushinteger(L, stats.bundleSwitches), lua_setfield(L, -2, "bundleSwitches");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrGraphicsIsFormatSupported(lua_State* L) {
|
||||
TextureFormat format = luax_checkenum(L, 1, TextureFormat, NULL);
|
||||
uint32_t features = 0;
|
||||
|
@ -1488,11 +1482,11 @@ static int l_lovrGraphicsNewPass(lua_State* L) {
|
|||
static const luaL_Reg lovrGraphics[] = {
|
||||
{ "init", l_lovrGraphicsInit },
|
||||
{ "submit", l_lovrGraphicsSubmit },
|
||||
{ "present", l_lovrGraphicsPresent },
|
||||
{ "wait", l_lovrGraphicsWait },
|
||||
{ "getDevice", l_lovrGraphicsGetDevice },
|
||||
{ "getFeatures", l_lovrGraphicsGetFeatures },
|
||||
{ "getLimits", l_lovrGraphicsGetLimits },
|
||||
{ "getStats", l_lovrGraphicsGetStats },
|
||||
{ "isFormatSupported", l_lovrGraphicsIsFormatSupported },
|
||||
{ "getWindowPass", l_lovrGraphicsGetWindowPass },
|
||||
{ "getDefaultFont", l_lovrGraphicsGetDefaultFont },
|
||||
|
|
|
@ -57,6 +57,10 @@ static int l_lovrModelGetData(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrModelGetMetadata(lua_State* L) {
|
||||
return luax_callmodeldata(L, "getMetadata", 1);
|
||||
}
|
||||
|
||||
static int l_lovrModelGetRootNode(lua_State* L) {
|
||||
return luax_callmodeldata(L, "getRootNode", 1);
|
||||
}
|
||||
|
@ -356,6 +360,7 @@ static int l_lovrModelGetTexture(lua_State* L) {
|
|||
|
||||
const luaL_Reg lovrModel[] = {
|
||||
{ "getData", l_lovrModelGetData },
|
||||
{ "getMetadata", l_lovrModelGetMetadata },
|
||||
{ "getRootNode", l_lovrModelGetRootNode },
|
||||
{ "getNodeCount", l_lovrModelGetNodeCount },
|
||||
{ "getNodeName", l_lovrModelGetNodeName },
|
||||
|
|
|
@ -700,7 +700,8 @@ typedef struct {
|
|||
bool gpu_init(gpu_config* config);
|
||||
void gpu_destroy(void);
|
||||
uint32_t gpu_begin(void);
|
||||
void gpu_submit(gpu_stream** streams, uint32_t count, bool present);
|
||||
void gpu_submit(gpu_stream** streams, uint32_t count);
|
||||
void gpu_present(void);
|
||||
bool gpu_is_complete(uint32_t tick);
|
||||
bool gpu_wait_tick(uint32_t tick);
|
||||
void gpu_wait_idle(void);
|
||||
|
|
|
@ -2315,7 +2315,7 @@ uint32_t gpu_begin() {
|
|||
return state.tick[CPU];
|
||||
}
|
||||
|
||||
void gpu_submit(gpu_stream** streams, uint32_t count, bool present) {
|
||||
void gpu_submit(gpu_stream** streams, uint32_t count) {
|
||||
gpu_tick* tick = &state.ticks[state.tick[CPU] & TICK_MASK];
|
||||
|
||||
VkCommandBuffer commands[COUNTOF(tick->streams)];
|
||||
|
@ -2323,35 +2323,43 @@ void gpu_submit(gpu_stream** streams, uint32_t count, bool present) {
|
|||
commands[i] = streams[i]->commands;
|
||||
}
|
||||
|
||||
VkPipelineStageFlags waitMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
|
||||
VkSubmitInfo submit = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.waitSemaphoreCount = present,
|
||||
.waitSemaphoreCount = !!state.surfaceSemaphore,
|
||||
.pWaitSemaphores = &state.surfaceSemaphore,
|
||||
.pWaitDstStageMask = &waitMask,
|
||||
.pWaitDstStageMask = &waitStage,
|
||||
.commandBufferCount = count,
|
||||
.pCommandBuffers = commands,
|
||||
.signalSemaphoreCount = present,
|
||||
.pSignalSemaphores = &tick->semaphores[1]
|
||||
.pCommandBuffers = commands
|
||||
};
|
||||
|
||||
VK(vkQueueSubmit(state.queue, 1, &submit, tick->fence), "Queue submit failed") {}
|
||||
state.surfaceSemaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (present) {
|
||||
VkPresentInfoKHR presentInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &tick->semaphores[1],
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &state.swapchain,
|
||||
.pImageIndices = &state.currentSurfaceTexture
|
||||
};
|
||||
void gpu_present() {
|
||||
VkSemaphore semaphore = state.ticks[state.tick[CPU] & TICK_MASK].semaphores[1];
|
||||
|
||||
VK(vkQueuePresentKHR(state.queue, &presentInfo), "Queue present failed") {}
|
||||
state.surfaceSemaphore = VK_NULL_HANDLE;
|
||||
state.currentSurfaceTexture = ~0u;
|
||||
}
|
||||
VkSubmitInfo submit = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &semaphore
|
||||
};
|
||||
|
||||
VK(vkQueueSubmit(state.queue, 1, &submit, VK_NULL_HANDLE), "Queue submit failed") {}
|
||||
|
||||
VkPresentInfoKHR present = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &semaphore,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &state.swapchain,
|
||||
.pImageIndices = &state.currentSurfaceTexture
|
||||
};
|
||||
|
||||
VK(vkQueuePresentKHR(state.queue, &present), "Queue present failed") {}
|
||||
state.currentSurfaceTexture = ~0u;
|
||||
}
|
||||
|
||||
bool gpu_is_complete(uint32_t tick) {
|
||||
|
|
|
@ -105,6 +105,7 @@ void lovrModelDataDestroy(void* ref) {
|
|||
map_free(&model->nodeMap);
|
||||
free(model->vertices);
|
||||
free(model->indices);
|
||||
free(model->metadata);
|
||||
free(model->data);
|
||||
free(model);
|
||||
}
|
||||
|
|
|
@ -156,6 +156,9 @@ typedef struct ModelData {
|
|||
uint32_t ref;
|
||||
void* data;
|
||||
|
||||
char* metadata;
|
||||
size_t metadataSize;
|
||||
|
||||
struct Blob** blobs;
|
||||
struct Image** images;
|
||||
ModelBuffer* buffers;
|
||||
|
|
|
@ -230,6 +230,11 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
binOffset = 0;
|
||||
}
|
||||
|
||||
model->metadata = malloc(jsonLength);
|
||||
lovrAssert(model->metadata, "Out of memory");
|
||||
memcpy(model->metadata, json, jsonLength);
|
||||
model->metadataSize = jsonLength;
|
||||
|
||||
// Parse JSON
|
||||
jsmn_parser parser;
|
||||
jsmn_init(&parser);
|
||||
|
|
|
@ -361,7 +361,6 @@ static struct {
|
|||
gpu_device_info device;
|
||||
gpu_features features;
|
||||
gpu_limits limits;
|
||||
GraphicsStats stats;
|
||||
Texture* window;
|
||||
Pass* windowPass;
|
||||
Font* defaultFont;
|
||||
|
@ -736,10 +735,6 @@ void lovrGraphicsGetLimits(GraphicsLimits* limits) {
|
|||
limits->pointSize = state.limits.pointSize;
|
||||
}
|
||||
|
||||
void lovrGraphicsGetStats(GraphicsStats* stats) {
|
||||
*stats = state.stats;
|
||||
}
|
||||
|
||||
bool lovrGraphicsIsFormatSupported(uint32_t format, uint32_t features) {
|
||||
uint8_t supports = state.features.formats[format];
|
||||
if (!features) return supports;
|
||||
|
@ -763,7 +758,6 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool present = false;
|
||||
uint32_t total = count + 1;
|
||||
gpu_stream** streams = tempAlloc(total * sizeof(gpu_stream*));
|
||||
gpu_barrier* barriers = tempAlloc(count * sizeof(gpu_barrier));
|
||||
|
@ -819,26 +813,24 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
|||
|
||||
Canvas* canvas = &pass->info.canvas;
|
||||
|
||||
for (uint32_t j = 0; j < COUNTOF(canvas->textures) && canvas->textures[j]; j++) {
|
||||
if (canvas->mipmap && canvas->textures[j]->info.mipmaps > 1) {
|
||||
barriers[i].prev |= GPU_PHASE_COLOR;
|
||||
if (canvas->mipmap) {
|
||||
for (uint32_t j = 0; j < COUNTOF(canvas->textures) && canvas->textures[j]; j++) {
|
||||
if (canvas->textures[j]->info.mipmaps > 1) {
|
||||
barriers[i].prev |= GPU_PHASE_COLOR;
|
||||
barriers[i].next |= GPU_PHASE_TRANSFER;
|
||||
barriers[i].flush |= GPU_CACHE_COLOR_WRITE;
|
||||
barriers[i].clear |= GPU_CACHE_TRANSFER_READ;
|
||||
mipmapTexture(pass->stream, canvas->textures[j], 0, ~0u);
|
||||
}
|
||||
}
|
||||
|
||||
if (canvas->depth.texture && canvas->depth.texture->info.mipmaps > 1) {
|
||||
barriers[i].prev |= GPU_PHASE_DEPTH_LATE;
|
||||
barriers[i].next |= GPU_PHASE_TRANSFER;
|
||||
barriers[i].flush |= GPU_CACHE_COLOR_WRITE;
|
||||
barriers[i].flush |= GPU_CACHE_DEPTH_WRITE;
|
||||
barriers[i].clear |= GPU_CACHE_TRANSFER_READ;
|
||||
mipmapTexture(pass->stream, canvas->textures[j], 0, ~0u);
|
||||
mipmapTexture(pass->stream, canvas->depth.texture, 0, ~0u);
|
||||
}
|
||||
|
||||
if (canvas->textures[j] == state.window) {
|
||||
present = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (canvas->mipmap && canvas->depth.texture && canvas->depth.texture->info.mipmaps > 1) {
|
||||
barriers[i].prev |= GPU_PHASE_DEPTH_LATE;
|
||||
barriers[i].next |= GPU_PHASE_TRANSFER;
|
||||
barriers[i].flush |= GPU_CACHE_DEPTH_WRITE;
|
||||
barriers[i].clear |= GPU_CACHE_TRANSFER_READ;
|
||||
mipmapTexture(pass->stream, canvas->depth.texture, 0, ~0u);
|
||||
}
|
||||
break;
|
||||
case PASS_COMPUTE:
|
||||
|
@ -958,20 +950,20 @@ void lovrGraphicsSubmit(Pass** passes, uint32_t count) {
|
|||
gpu_stream_end(streams[i]);
|
||||
}
|
||||
|
||||
gpu_submit(streams, total, present);
|
||||
|
||||
state.stats.pipelineSwitches = 0;
|
||||
state.stats.bundleSwitches = 0;
|
||||
|
||||
if (present) {
|
||||
state.window->gpu = NULL;
|
||||
state.window->renderView = NULL;
|
||||
}
|
||||
gpu_submit(streams, total);
|
||||
|
||||
state.stream = NULL;
|
||||
state.active = false;
|
||||
}
|
||||
|
||||
void lovrGraphicsPresent() {
|
||||
if (state.window->gpu) {
|
||||
state.window->gpu = NULL;
|
||||
state.window->renderView = NULL;
|
||||
gpu_present();
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsWait() {
|
||||
gpu_wait_idle();
|
||||
}
|
||||
|
@ -2857,8 +2849,6 @@ static void lovrModelReskin(Model* model) {
|
|||
gpu_compute(state.stream, (skin->vertexCount + subgroupSize - 1) / subgroupSize, 1, 1);
|
||||
gpu_compute_end(state.stream);
|
||||
baseVertex += skin->vertexCount;
|
||||
state.stats.pipelineSwitches++;
|
||||
state.stats.bundleSwitches++;
|
||||
}
|
||||
|
||||
state.hasReskin = true;
|
||||
|
@ -3040,8 +3030,6 @@ static void lovrTallyResolve(Tally* tally, uint32_t index, uint32_t count, gpu_b
|
|||
gpu_push_constants(stream, shader, &constants, sizeof(constants));
|
||||
gpu_compute(stream, (count + 31) / 32, 1, 1);
|
||||
gpu_compute_end(stream);
|
||||
state.stats.pipelineSwitches++;
|
||||
state.stats.bundleSwitches++;
|
||||
}
|
||||
|
||||
// Pass
|
||||
|
@ -4022,7 +4010,6 @@ static void flushPipeline(Pass* pass, Draw* draw, Shader* shader) {
|
|||
}
|
||||
|
||||
gpu_bind_pipeline(pass->stream, state.pipelines.data[index], false);
|
||||
state.stats.pipelineSwitches++;
|
||||
pipeline->dirty = false;
|
||||
}
|
||||
|
||||
|
@ -4055,7 +4042,6 @@ static void flushBindings(Pass* pass, Shader* shader) {
|
|||
gpu_bundle* bundle = getBundle(shader->layout);
|
||||
gpu_bundle_write(&bundle, &info, 1);
|
||||
gpu_bind_bundle(pass->stream, shader->gpu, set, bundle, NULL, 0);
|
||||
state.stats.bundleSwitches++;
|
||||
tempPop(stack);
|
||||
}
|
||||
|
||||
|
@ -4100,7 +4086,6 @@ static void flushBuiltins(Pass* pass, Draw* draw, Shader* shader) {
|
|||
gpu_bundle* bundle = getBundle(state.builtinLayout);
|
||||
gpu_bundle_write(&bundle, &bundleInfo, 1);
|
||||
gpu_bind_bundle(pass->stream, shader->gpu, 0, bundle, NULL, 0);
|
||||
state.stats.bundleSwitches++;
|
||||
}
|
||||
|
||||
float m[16];
|
||||
|
@ -4128,12 +4113,10 @@ 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);
|
||||
state.stats.bundleSwitches++;
|
||||
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);
|
||||
state.stats.bundleSwitches++;
|
||||
pass->materialDirty = false;
|
||||
}
|
||||
}
|
||||
|
@ -5077,7 +5060,6 @@ void lovrPassCompute(Pass* pass, uint32_t x, uint32_t y, uint32_t z, Buffer* ind
|
|||
|
||||
if (pass->pipeline->dirty) {
|
||||
gpu_bind_pipeline(pass->stream, pipeline, true);
|
||||
state.stats.pipelineSwitches++;
|
||||
pass->pipeline->dirty = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,11 +83,6 @@ typedef struct {
|
|||
float pointSize;
|
||||
} GraphicsLimits;
|
||||
|
||||
typedef struct {
|
||||
uint32_t pipelineSwitches;
|
||||
uint32_t bundleSwitches;
|
||||
} GraphicsStats;
|
||||
|
||||
enum {
|
||||
TEXTURE_FEATURE_SAMPLE = (1 << 0),
|
||||
TEXTURE_FEATURE_FILTER = (1 << 1),
|
||||
|
@ -105,11 +100,11 @@ void lovrGraphicsDestroy(void);
|
|||
void lovrGraphicsGetDevice(GraphicsDevice* device);
|
||||
void lovrGraphicsGetFeatures(GraphicsFeatures* features);
|
||||
void lovrGraphicsGetLimits(GraphicsLimits* limits);
|
||||
void lovrGraphicsGetStats(GraphicsStats* stats);
|
||||
bool lovrGraphicsIsFormatSupported(uint32_t format, uint32_t features);
|
||||
void lovrGraphicsGetShaderCache(void* data, size_t* size);
|
||||
|
||||
void lovrGraphicsSubmit(Pass** passes, uint32_t count);
|
||||
void lovrGraphicsPresent(void);
|
||||
void lovrGraphicsWait(void);
|
||||
|
||||
// Buffer
|
||||
|
|
|
@ -193,7 +193,26 @@ static Texture* desktop_getTexture(void) {
|
|||
}
|
||||
|
||||
static Pass* desktop_getPass(void) {
|
||||
return lovrGraphicsGetWindowPass();
|
||||
Pass* pass = lovrGraphicsGetWindowPass();
|
||||
lovrPassReset(pass);
|
||||
|
||||
float position[4], orientation[4];
|
||||
desktop_getViewPose(0, position, orientation);
|
||||
|
||||
float viewMatrix[16];
|
||||
mat4_fromQuat(viewMatrix, orientation);
|
||||
memcpy(viewMatrix + 12, position, 3 * sizeof(float));
|
||||
mat4_invert(viewMatrix);
|
||||
|
||||
float projection[16];
|
||||
float left, right, up, down;
|
||||
desktop_getViewAngles(0, &left, &right, &up, &down);
|
||||
mat4_fov(projection, left, right, up, down, state.clipNear, state.clipFar);
|
||||
|
||||
lovrPassSetViewMatrix(pass, 0, viewMatrix);
|
||||
lovrPassSetProjection(pass, 0, projection);
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
static void desktop_submit(void) {
|
||||
|
|
Loading…
Reference in New Issue