From 686a4f5e3ef4341353f3302bb8bcb934e442895e Mon Sep 17 00:00:00 2001 From: mrq Date: Tue, 19 Jul 2022 16:59:00 -0500 Subject: [PATCH] Commit for 2022.07.19 16-59-42.7z --- bin/data/config.json | 37 +++--- bin/data/entities/burger.json | 2 +- bin/data/entities/cornell.json | 2 +- .../entities/gui/mainmenu/scripts/menu.lua | 1 + bin/data/entities/gui/mainmenu/start.json | 2 +- bin/data/entities/gui/pause/scripts/menu.lua | 1 + bin/data/entities/model.json | 2 +- bin/data/entities/playerModel.json | 2 +- bin/data/entities/prop.json | 2 +- bin/data/entities/scripts/door.lua | 1 + bin/data/entities/scripts/player.lua | 9 +- bin/data/scenes/cornell/cornell.json | 2 +- bin/data/scenes/cornell/scene.json | 52 +------- bin/data/scenes/scene.json | 41 ++++++ bin/data/scenes/sm64/scene.json | 70 +---------- bin/data/scenes/sm64/sm64.json | 2 +- .../sourceengine/base_sourceengine.json | 6 +- .../scenes/sourceengine/gm_construct.json | 5 +- .../scenes/sourceengine/mds_mcdonalds.json | 5 +- bin/data/scenes/sourceengine/player.json | 5 +- .../scenes/sourceengine/rp_downtown_v2.json | 7 +- bin/data/scenes/sourceengine/scene.json | 47 ++----- .../scenes/sourceengine/sh2_mcdonalds.json | 5 +- .../scenes/sourceengine/sourceengine.json | 2 + bin/data/scenes/sourceengine/ss2_medsci1.json | 18 +++ bin/data/scenes/ss2/craeture.json | 2 +- bin/data/scenes/ss2/medsci.json | 6 +- bin/data/scenes/ss2/scene.json | 36 +----- bin/data/scenes/ss2/scripts/camera.lua | 23 ++-- bin/data/scenes/ss2/scripts/lift.lua | 4 +- bin/data/scenes/startmenu/scene.json | 5 - client/client/ext.cpp | 8 ++ engine/inc/uf/engine/object/object.h | 8 ++ engine/inc/uf/engine/object/object.inl | 9 ++ engine/inc/uf/ext/vulkan/buffer.h | 6 - engine/inc/uf/ext/vulkan/device.h | 54 +++++--- engine/inc/uf/utils/io/inputs.h | 4 + engine/src/engine/behavior/behavior.cpp | 2 +- engine/src/engine/graph/convert.cpp | 2 +- engine/src/engine/graph/graph.cpp | 54 +++++++- engine/src/engine/object/behavior.cpp | 4 +- engine/src/engine/object/behaviors/graph.cpp | 7 +- .../src/engine/object/behaviors/loading.cpp | 2 +- engine/src/engine/object/object.cpp | 100 ++++++++++++++- engine/src/ext/imgui/imgui.cpp | 6 +- engine/src/ext/lua/usertypes/object.cpp | 119 +++++++++++------- engine/src/ext/openvr/openvr.cpp | 2 +- engine/src/ext/vulkan/buffer.cpp | 40 +++--- engine/src/ext/vulkan/device.cpp | 103 +++++++-------- engine/src/ext/vulkan/graphic.cpp | 20 +-- engine/src/ext/vulkan/rendermode.cpp | 12 +- engine/src/ext/vulkan/rendermodes/base.cpp | 10 +- engine/src/ext/vulkan/rendermodes/compute.cpp | 2 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 2 +- .../ext/vulkan/rendermodes/rendertarget.cpp | 11 +- engine/src/ext/vulkan/texture.cpp | 75 ++++++++--- engine/src/ext/vulkan/vulkan.cpp | 43 ++++++- engine/src/utils/io/inputs.cpp | 4 +- ext/behaviors/light/behavior.cpp | 19 +-- ext/behaviors/player/behavior.cpp | 24 +++- ext/behaviors/player/model/behavior.cpp | 4 +- ext/behaviors/raytrace/behavior.cpp | 31 ++++- ext/behaviors/scene/behavior.cpp | 104 +++++++++------ ext/behaviors/scene/behavior.h | 2 +- ext/behaviors/soundemitter/behavior.cpp | 2 +- ext/behaviors/voxelizer/behavior.cpp | 50 ++++---- ext/gui/behavior.cpp | 51 ++++---- ext/main.cpp | 4 +- 68 files changed, 846 insertions(+), 558 deletions(-) create mode 100644 bin/data/scenes/sourceengine/ss2_medsci1.json diff --git a/bin/data/config.json b/bin/data/config.json index c1640be4..3937cb73 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -1,18 +1,25 @@ { "engine": { "scenes": { - "start": "SS2", + "start": "SourceEngine", "matrix": { "reverseInfinite": true }, "meshes": { "interleaved": false }, "lights": { "enabled": true, "useLightmaps": false, - "max": 48 - }, - "shadows": { - "enabled": true, - "update": 4, - "max": 24, - "samples": 1 + "max": 48, + "shadows": { + "enabled": true, + "update": 4, + "max": 24, + "samples": 1 + }, + "bloom": { + "scale": 1.0, + "strength": 0.125, + "sigma": 0.8, + "samples": 5, + "threshold": 1.0 + } }, "textures": { "max": { @@ -45,13 +52,6 @@ "samples": 1, "paths": 2, "frameAccumulationMinimum": 0 - }, - "bloom": { - "scale": 1.0, - "strength": 0.125, - "sigma": 0.8, - "samples": 5, - "threshold": 1.0 } }, "graph": { @@ -298,6 +298,9 @@ }, "loader": { "assert": true + }, + "hooks": { + "defer lazy calls": true } } }, @@ -318,8 +321,8 @@ "mode" : "windowed", // fullscreen, borderless, windowed "icon" : "./data/textures/icon.png", // "size" : [ 1920, 1080 ], - "size" : [ 1280, 720 ], - // "size" : [ 960, 540 ], + // "size" : [ 1280, 720 ], + "size" : [ 960, 540 ], // "size" : [ 640, 480 ], // "size" : [ 256, 224 ], "title" : "Grimgram", diff --git a/bin/data/entities/burger.json b/bin/data/entities/burger.json index 1406f84a..f207132c 100644 --- a/bin/data/entities/burger.json +++ b/bin/data/entities/burger.json @@ -34,7 +34,7 @@ "type": "bounding box", "recenter": false }, - "model": { + "graph": { "exporter": { "enabled": true, "unwrap": false, diff --git a/bin/data/entities/cornell.json b/bin/data/entities/cornell.json index 1a279e31..8033b870 100644 --- a/bin/data/entities/cornell.json +++ b/bin/data/entities/cornell.json @@ -24,7 +24,7 @@ "metadata": { "track": true, "hide": true, - "model": { + "graph": { "lightmap": false, "exporter": { "enabled": false, diff --git a/bin/data/entities/gui/mainmenu/scripts/menu.lua b/bin/data/entities/gui/mainmenu/scripts/menu.lua index 84faf4c8..7d6ec234 100644 --- a/bin/data/entities/gui/mainmenu/scripts/menu.lua +++ b/bin/data/entities/gui/mainmenu/scripts/menu.lua @@ -8,6 +8,7 @@ Static = { end } +local ent = ent local scene = entities.currentScene() local controller = entities.controller() local camera = controller:getComponent("Camera") diff --git a/bin/data/entities/gui/mainmenu/start.json b/bin/data/entities/gui/mainmenu/start.json index 9e18c5f7..23fc52ca 100644 --- a/bin/data/entities/gui/mainmenu/start.json +++ b/bin/data/entities/gui/mainmenu/start.json @@ -23,7 +23,7 @@ "events": { "click": { "name": "game:Scene.Load", - "payload": { "scene": "SS2" } + "payload": { "scene": "SourceEngine" } } }, "text settings": { diff --git a/bin/data/entities/gui/pause/scripts/menu.lua b/bin/data/entities/gui/pause/scripts/menu.lua index 5f9db328..f5373f66 100644 --- a/bin/data/entities/gui/pause/scripts/menu.lua +++ b/bin/data/entities/gui/pause/scripts/menu.lua @@ -1,3 +1,4 @@ +local ent = ent local scene = entities.currentScene() local metadata = ent:getComponent("Metadata") local masterdata = scene:getComponent("Metadata") diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index 125fba46..6f163190 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -9,7 +9,7 @@ "scale": [ 1, 1, 1 ] }, "metadata": { - "model": { + "graph": { "debug": { "no cleanup": false, "print": { diff --git a/bin/data/entities/playerModel.json b/bin/data/entities/playerModel.json index c85cbbde..c8f1796e 100644 --- a/bin/data/entities/playerModel.json +++ b/bin/data/entities/playerModel.json @@ -28,7 +28,7 @@ "metadata": { "track": true, "hide": true, - "model": { + "graph": { "debug": { "print": { "animations": true diff --git a/bin/data/entities/prop.json b/bin/data/entities/prop.json index f8dbb274..2167c79f 100644 --- a/bin/data/entities/prop.json +++ b/bin/data/entities/prop.json @@ -11,7 +11,7 @@ "mass": 10, "type": "bounding box", - "recenter": true + "recenter": false } } } \ No newline at end of file diff --git a/bin/data/entities/scripts/door.lua b/bin/data/entities/scripts/door.lua index d72079eb..b32db393 100644 --- a/bin/data/entities/scripts/door.lua +++ b/bin/data/entities/scripts/door.lua @@ -1,3 +1,4 @@ +local ent = ent local scene = entities.currentScene() local controller = entities.controller() diff --git a/bin/data/entities/scripts/player.lua b/bin/data/entities/scripts/player.lua index 5c6a578e..c82ce54c 100644 --- a/bin/data/entities/scripts/player.lua +++ b/bin/data/entities/scripts/player.lua @@ -1,3 +1,4 @@ +local ent = ent local scene = entities.currentScene() local metadata = ent:getComponent("Metadata") local transform = ent:getComponent("Transform") @@ -49,7 +50,7 @@ light.entity:setComponent("Metadata", { light = { power = 0 } }) local playSound = function( key, loop ) if not loop then loop = false end local url = "/ui/" .. key .. ".ogg" - ent:queueHook("sound:Emit.%UID%", { + ent:callHook("sound:Emit.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]), spatial = true, streamed = true, @@ -59,7 +60,7 @@ local playSound = function( key, loop ) end local stopSound = function( key ) local url = "/ui/" .. key .. ".ogg" - ent:queueHook("sound:Stop.%UID%", { + ent:callHook("sound:Stop.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]) }, 0) end @@ -118,9 +119,9 @@ ent:bind( "tick", function(self) depth = depth, } if prop then - prop:callHook("entity:Use.%UID%", payload) + prop:lazyCallHook("entity:Use.%UID%", payload) end - ent:callHook("entity:Use.%UID%", payload) + ent:lazyCallHook("entity:Use.%UID%", payload) end -- update HOLP diff --git a/bin/data/scenes/cornell/cornell.json b/bin/data/scenes/cornell/cornell.json index ef52aec9..560b1091 100644 --- a/bin/data/scenes/cornell/cornell.json +++ b/bin/data/scenes/cornell/cornell.json @@ -11,7 +11,7 @@ { "filename": "./models/sponza-cornell/graph.json" } ], "metadata": { - "model": { + "graph": { "baking": { "enabled": false, "resolution": 2048, diff --git a/bin/data/scenes/cornell/scene.json b/bin/data/scenes/cornell/scene.json index c0ced330..f20f895e 100644 --- a/bin/data/scenes/cornell/scene.json +++ b/bin/data/scenes/cornell/scene.json @@ -4,60 +4,10 @@ // "./loading.json" "./cornell.json" ], - "system": { - "hot reload": { - "enabled": true - }, - "renderer": { - "clear values": [ - [ 0, 0, 0, 0 ] - ], - "shader": { - "mode": 1, - "scalar": 16, - "parameters": [ 0, 0, 0, "time" ] - } - } - }, "metadata": { - "menus": { - "pause": "/gui/pause/menu.json" - }, - "bloom": { - "scale": 1.0, - "strength": 0.125, - "sigma": 0.8, - "samples": 5 - }, - "rt": { - "defaultRayBounds": [ 0.001, 1024.0 ], - "alphaTestOffset": 0.001, - "samples": 1, - "paths": 4, - "frameAccumulationMinimum": 0 - }, "light": { - "exposure": 1.0, - "gamma": 1.0, - "brightnessThreshold": 1.2, - // "ambient": [ 0.0, 0.0, 0.0 ], - "ambient": [ 0.5, 0.5, 0.5 ], - - "fog": { - "color": [ 0.025, 0.025, 0.1 ], - "step scale": 0.0, - "range": [ 1, 1 ], - "absorbtion": 0.85, - "density": { - "threshold": 0.5, - "multiplier": 5.0, - "scale": 50.0, - "offset": "time" - } - }, - "should": true, - "shadows": true + "ambient": [ 0.5, 0.5, 0.5 ] } } } \ No newline at end of file diff --git a/bin/data/scenes/scene.json b/bin/data/scenes/scene.json index 43eef2eb..f138fbf5 100644 --- a/bin/data/scenes/scene.json +++ b/bin/data/scenes/scene.json @@ -7,6 +7,21 @@ "SceneBehavior", "ExtSceneBehavior" ], + "system": { + "hot reload": { + "enabled": true + }, + "renderer": { + "clear values": [ + [ 0, 0, 0, 0 ] + ], + "shader": { + "mode": 1, + "scalar": 16, + "parameters": [ 0, 0, 0, "time" ] + } + } + }, "metadata": { // sky, and not skybox, so i can supply parameters for global lighting "sky": { @@ -14,6 +29,32 @@ "box": { "filename": "/skybox/%d.png" } + }, + "menus": { + "pause": "/gui/pause/menu.json" + }, + "light": { + "enabled": true, + + "ambient": [ 0.0, 0.0, 0.0 ], + // "ambient": [ 0.1, 0.1, 0.2 ], + + "exposure": 1.0, + "gamma": 2.2, + "brightnessThreshold": 1.2, + + "bloom": { + "scale": 1.0, + "strength": 0.125, + "sigma": 0.8, + "samples": 5 + }, + "shadows": { + "enabled": true + } + }, + "noise": { + "size": [ 32, 32, 32 ] } } } \ No newline at end of file diff --git a/bin/data/scenes/sm64/scene.json b/bin/data/scenes/sm64/scene.json index 4f5147da..30226890 100644 --- a/bin/data/scenes/sm64/scene.json +++ b/bin/data/scenes/sm64/scene.json @@ -4,36 +4,8 @@ // "./loading.json", "./sm64.json" ], - "system": { - "hot reload": { - "enabled": true - }, - "renderer": { - "shader": { - "mode": 1, - "scalar": 16, - "parameters": [ 0, 0, 0, "time" ], - "frame accumulate limit": 0 - }, - "clear values": [ - [ 1, 1, 1, 0 ] - ] - } - }, "metadata": { - "menus": { - "pause": "/gui/pause/menu.json" - }, - "bloom": { - "scale": 6.0, - "strength": 0.125, - "sigma": 0.125, - "samples": 8 - }, "light": { - "exposure": 1.0, - "gamma": 1.0, - "brightnessThreshold": 1.2, // "ambient": [ 0, 0, 0 ], // "ambient": [ 0.025, 0.025, 0.025 ], // "ambient": [ 0.075, 0.075, 0.075 ], @@ -42,48 +14,8 @@ // "ambient": [ 0.8, 0.8, 0.8 ], "fog-": { - "color": [ 0.5, 0.5, 0.5 ], - "range": [ 16, 32 ], - "step scale": 2, - "absorbtion": 0.01, - "density": { - "threshold": 0.35, - "multiplier": 5.0, - "scale": 25.0, - "offset": [0, -1, 1], - "timescale": 8 - } - }, - "should": true, - "shadows": true - }, - "noise": { - "size": [ 32, 32, 32 ] - }, - "vxgi": { - /* - "limiter": 1, - "size": 96, - "dispatch": 8, - "cascades": 2, - "cascadePower": 4, - "voxelizeScale": 1, - "shadows": 0, - */ - "occlusionFalloff": 2, - "traceStartOffsetFactor": 1, - "granularity": 2, - "extents": { - "min": [ -1.5, -1.5, -1.5 ], - "max": [ 1.5, 1.5, 1.5 ] + } - }, - "rt": { - "defaultRayBounds": [ 0.001, 1024.0 ], - "alphaTestOffset": 1.125, - "samples": 1, - "paths": 1, - "frameAccumulationMinimum": 0 } } } \ No newline at end of file diff --git a/bin/data/scenes/sm64/sm64.json b/bin/data/scenes/sm64/sm64.json index 1da53c2e..4140f707 100644 --- a/bin/data/scenes/sm64/sm64.json +++ b/bin/data/scenes/sm64/sm64.json @@ -5,7 +5,7 @@ { "filename": "./models/sm64_bbb/graph.json" } ], "metadata": { - "model": { + "graph": { "baking": { "enabled": true, "resolution": 2048, diff --git a/bin/data/scenes/sourceengine/base_sourceengine.json b/bin/data/scenes/sourceengine/base_sourceengine.json index ef76a46a..34e00cb0 100644 --- a/bin/data/scenes/sourceengine/base_sourceengine.json +++ b/bin/data/scenes/sourceengine/base_sourceengine.json @@ -1,7 +1,7 @@ { "import": "/model.json", "metadata": { - "model": { + "graph": { // "renderer": { "separate": true }, "baking": { "enabled": false }, "tags": { @@ -14,7 +14,7 @@ }, "info_player_spawn": { "action": "attach", "filename": "./player.json", "transform": { "orientation": [ 0, 1, 0, 0 ] } }, "light_environment": { "transform": { "orientation": [0,0,0,1] }, "light": { - "power": 100000, + "power": 1, "global": true, "bias": { "constant": 1.25, @@ -26,7 +26,7 @@ } }, // regexp matches - "/^worldspawn/": { "physics": { "type": "mesh", "static": true } }, + "/^worldspawn_/": { "physics": { "type": "mesh", "static": true } }, "/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "/^prop_static/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ }, diff --git a/bin/data/scenes/sourceengine/gm_construct.json b/bin/data/scenes/sourceengine/gm_construct.json index a789edd5..7e9cd930 100644 --- a/bin/data/scenes/sourceengine/gm_construct.json +++ b/bin/data/scenes/sourceengine/gm_construct.json @@ -5,7 +5,10 @@ { "filename": "./models/gm_construct/graph.json" } ], "metadata": { - "model": { + "graph": { + "assets": [ + "./audio/soundscape/ambience.ogg" + ], "tags": { // exact matches "worldspawn_skybox": { "ignore": true }, diff --git a/bin/data/scenes/sourceengine/mds_mcdonalds.json b/bin/data/scenes/sourceengine/mds_mcdonalds.json index 3a0ad4fd..77b02685 100644 --- a/bin/data/scenes/sourceengine/mds_mcdonalds.json +++ b/bin/data/scenes/sourceengine/mds_mcdonalds.json @@ -5,7 +5,10 @@ { "filename": "./models/mds_mcdonalds/graph.json" } ], "metadata": { - "model": { + "graph": { + "assets": [ + "./audio/soundscape/sh2_ambience.ogg" + ], "tags": { // exact matches "func_door_rotating_5473": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [1,0,0] } } }, diff --git a/bin/data/scenes/sourceengine/player.json b/bin/data/scenes/sourceengine/player.json index bd6ad5ef..b41da045 100644 --- a/bin/data/scenes/sourceengine/player.json +++ b/bin/data/scenes/sourceengine/player.json @@ -2,6 +2,9 @@ "import": "/player.json", "assets": [ // { "filename": "/gui/hud/hud.json", "delay": 0 } - ] + ], + "transform": { + "orientation": [ 0, 1, 0, 0 ] + } // "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/rp_downtown_v2.json b/bin/data/scenes/sourceengine/rp_downtown_v2.json index 03c251b1..8da0ecc6 100644 --- a/bin/data/scenes/sourceengine/rp_downtown_v2.json +++ b/bin/data/scenes/sourceengine/rp_downtown_v2.json @@ -1,13 +1,14 @@ { "import": "./base_sourceengine.json", "assets": [ - "./audio/soundscape/ambience.ogg", - // { "filename": "./models/rp_downtown_v2.glb" } { "filename": "./models/rp_downtown_v2/graph.json" } ], "metadata": { - "model": { + "graph": { + "assets": [ + "./audio/soundscape/ambience.ogg" + ], "renderer": { "separate": true }, "tags": { // exact matches diff --git a/bin/data/scenes/sourceengine/scene.json b/bin/data/scenes/sourceengine/scene.json index c81771eb..a71142bf 100644 --- a/bin/data/scenes/sourceengine/scene.json +++ b/bin/data/scenes/sourceengine/scene.json @@ -1,41 +1,24 @@ { "import": "/scene.json", "assets": [ - "./audio/soundscape/sh2_ambience.ogg", "./sourceengine.json" // "./loading.json" ], - "system": { - "hot reload": { - "enabled": true - }, - "renderer": { - "clear values": [ - [ 0, 0, 0, 0 ] - ], - "shader": { - "mode": 1, - "scalar": 16, - "parameters": [ 0, 0, 0, "time" ] - } - } - }, "metadata": { - "menus": { - "pause": "/gui/pause/menu.json" - }, "light": { - "exposure": 1.0, - "gamma": 1.0, - - // "ambient": [ 0, 0, 0 ], - "ambient": [ 0.05, 0.05, 0.05 ], + "ambient": [ 0, 0, 0 ], + // "ambient": [ 0.05, 0.05, 0.05 ], // "ambient": [ 0.15, 0.15, 0.15 ], // "ambient": [ 0.5, 0.5, 0.5 ], // "ambient": [ 0.8, 0.8, 0.8 ], + // "ambient": [ 0.1, 0.1, 0.2 ], + + "exposure": 0.25, + "gamma": 2.2, + "brightnessThreshold": 1.2, "fog": { - "color": [ 0.5, 0.5, 0.5 ], + "color": [ 0.1, 0.1, 0.1 ], "range": [ 64, 256 ], "step scale": 2, "absorbtion": 0.0125, @@ -46,19 +29,7 @@ "offset": [0.2, 0, 1], "timescale": 8 } - }, - "should": true, - "shadows": true - }, - "noise": { - "size": [ 32, 32, 32 ] - }, - "rt": { - "defaultRayBounds": [ 0.5, 1024.0 ], - "alphaTestOffset": 0.01, - "samples": 1, - "paths": 1, - "frameAccumulationMinimum": 0 + } } } } \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/sh2_mcdonalds.json b/bin/data/scenes/sourceengine/sh2_mcdonalds.json index abf90f2d..9e7d6b55 100644 --- a/bin/data/scenes/sourceengine/sh2_mcdonalds.json +++ b/bin/data/scenes/sourceengine/sh2_mcdonalds.json @@ -5,7 +5,10 @@ { "filename": "./models/sh2_mcdonalds/graph.json" } ], "metadata": { - "model": { + "graph": { + "assets": [ + "./audio/soundscape/sh2_ambience.ogg" + ], "tags": { // exact matches "worldspawn_sh2": { diff --git a/bin/data/scenes/sourceengine/sourceengine.json b/bin/data/scenes/sourceengine/sourceengine.json index 055995dd..2f1ce5e4 100644 --- a/bin/data/scenes/sourceengine/sourceengine.json +++ b/bin/data/scenes/sourceengine/sourceengine.json @@ -1,4 +1,6 @@ { +// "import": "./rp_downtown_v2.json" +// "import": "./ss2_medsci1.json" "import": "./sh2_mcdonalds.json" // "import": "./gm_construct.json" } \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/ss2_medsci1.json b/bin/data/scenes/sourceengine/ss2_medsci1.json new file mode 100644 index 00000000..ad3c42a8 --- /dev/null +++ b/bin/data/scenes/sourceengine/ss2_medsci1.json @@ -0,0 +1,18 @@ +{ + "import": "./base_sourceengine.json", + "assets": [ + // { "filename": "./models/ss2_medsci1.glb" } + { "filename": "./models/ss2_medsci1/graph.json" } + ], + "metadata": { + "graph": { + "assets": [ + "./audio/music/medsci1.ogg" + ], + "tags": { + "/^prop_/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } }, + "/^func_/": { "action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } } + } + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/ss2/craeture.json b/bin/data/scenes/ss2/craeture.json index b8dbef80..7c419973 100644 --- a/bin/data/scenes/ss2/craeture.json +++ b/bin/data/scenes/ss2/craeture.json @@ -9,7 +9,7 @@ "scale": [8, 8, 8] }, "metadata": { - "model": { + "graph": { "cull mode": "none" } } diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index 2e774461..3ffc4ac8 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -17,7 +17,7 @@ // { "filename": "./models/medsci/graph.json" } ], "metadata": { - "model": { + "graph": { "baking": { "enabled": true, "resolution": 2048 @@ -41,8 +41,8 @@ "light_30145": { "light": { "power": 120 } }, - "/^prop_camera_.+?_light/": { /*"bake": false,*/ "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, - "/prop_camera_/": { /*"bake": false,*/ "action": "load", "payload": { "import": "./camera.json" } }, + "/^prop_camera_\\d+_light/": { /*"bake": false,*/ "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, + "/^prop_camera_\\d+$/": { /*"bake": false,*/ "action": "load", "payload": { "import": "./camera.json" } }, "func_movelinear_57637": { /*"bake": false,*/ "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,8.6,0 ] } } }, "func_movelinear_82820": { /*"bake": false,*/ "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,9.2,0 ] } } }, diff --git a/bin/data/scenes/ss2/scene.json b/bin/data/scenes/ss2/scene.json index de5c3307..d3b411ba 100644 --- a/bin/data/scenes/ss2/scene.json +++ b/bin/data/scenes/ss2/scene.json @@ -5,38 +5,10 @@ // "./loading.json" "./medsci.json" ], - "system": { - "hot reload": { - "enabled": true - }, - "renderer": { - "clear values": [ - [ 0, 0, 0, 0 ] - ], - "shader": { - "mode": 1, - "scalar": 16, - "parameters": [ 0, 0, 0, "time" ] - } - } - }, "metadata": { - "menus": { - "pause": "/gui/pause/menu.json" - }, - "bloom": { - "scale": 1.0, - "strength": 0.125, - "sigma": 0.8, - "samples": 5 - }, "light": { - "exposure": 1.0, - "gamma": 1.0, - "brightnessThreshold": 1.2, - - // "ambient": [ 0.0, 0.0, 0.0 ], - "ambient": [ 0.1, 0.1, 0.2 ], + "ambient": [ 0.0, 0.0, 0.0 ], + // "ambient": [ 0.1, 0.1, 0.2 ], "fog": { "color": [ 0.025, 0.025, 0.1 ], @@ -49,9 +21,7 @@ "scale": 50.0, "offset": "time" } - }, - "should": true, - "shadows": true + } } } } \ No newline at end of file diff --git a/bin/data/scenes/ss2/scripts/camera.lua b/bin/data/scenes/ss2/scripts/camera.lua index 9e16b147..92808e7c 100644 --- a/bin/data/scenes/ss2/scripts/camera.lua +++ b/bin/data/scenes/ss2/scripts/camera.lua @@ -1,12 +1,15 @@ +local ent = ent local scene = entities.currentScene() local controller = entities.controller() local controllerTransform = controller:getComponent("Transform") local timer = Timer.new() -if not timer:running() then - timer:start(); -end +if not timer:running() then timer:start() end + local metadata = ent:getComponent("Metadata") -local soundEmitter = ent:loadChild("/sound.json",true) +local transform = ent:getComponent("Transform") +local physicsState = ent:getComponent("PhysicsState") + +local soundEmitter = ent --ent:loadChild("/sound.json",true) local playSound = function( key ) if not loop then loop = false end local url = "./audio/sfx/" .. key .. ".ogg" @@ -36,7 +39,6 @@ local stopSoundscape = function( key ) end local target = Vector3f(0,0,0) -local transform = ent:getComponent("Transform") local speed = metadata["speed"] or 1.0 / 3.0 local angle = metadata["angle"] or 1.5 transform.orientation = Quaternion.axisAngle( Vector3f(0,1,0), 1.5 ) @@ -62,11 +64,6 @@ ent:bind( "tick", function(self) local angleThreshold = metadata["sensitivity"] or 20 - local controllerPosition = Vector3f(controllerTransform.position.x, 0, controllerTransform.position.z) - local cameraPosition = Vector3f(transform.position.x, 0, transform.position.z) - local distance = cameraPosition:distance(controllerPosition) - local direction = cameraPosition - controllerPosition - local lightTransform = light and light:getComponent("Transform") or nil local lightMetadata = light and light:getComponent("Metadata") or {} if lightTransform ~= nil then @@ -76,6 +73,10 @@ ent:bind( "tick", function(self) end end + local controllerPosition = Vector3f(controllerTransform.position.x, 0, controllerTransform.position.z) + local cameraPosition = Vector3f(transform.position.x, 0, transform.position.z) + local distance = cameraPosition:distance(controllerPosition) + local direction = cameraPosition - controllerPosition local angle = math.acos(transform.orientation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926 if angle < angleThreshold and distance < 16 then if watch == 0 then @@ -181,11 +182,13 @@ ent:bind( "tick", function(self) delta = delta + time.delta() * speed local nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 ) +--[[ -- stop if we are going to look away from player local angleNext = math.acos(nextRotation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926 if watch > 0 and angleNext > angle then delta = delta - time.delta() * speed * 3 nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 ) end +]] transform.orientation = nextRotation end ) \ No newline at end of file diff --git a/bin/data/scenes/ss2/scripts/lift.lua b/bin/data/scenes/ss2/scripts/lift.lua index fae90b18..437833ed 100644 --- a/bin/data/scenes/ss2/scripts/lift.lua +++ b/bin/data/scenes/ss2/scripts/lift.lua @@ -1,3 +1,4 @@ +local ent = ent local scene = entities.currentScene() local controller = entities.controller() @@ -10,7 +11,6 @@ local target = Vector3f(0,0,0) local transform = ent:getComponent("Transform") local metadata = ent:getComponent("Metadata") local physics = ent:getComponent("Physics") -local bullet = ent:getComponent("Bullet") -- local velocty = physics:linearVelocity() local speed = metadata["speed"] or 1.0 local starting = transform.position + Vector3f(0,0,0) @@ -73,10 +73,8 @@ ent:bind( "tick", function(self) stopSound("lift_start") playSound("lift_stop") startingSound = true - -- bullet:setVelocity( Vector3f(0,0,0) ) -- physics:setLinearVelocity( Vector3f(0,0,0) ) else - -- bullet:setVelocity( Vector3f(0,direction,0) ) -- physics:setLinearVelocity( Vector3f(0,direction / math.abs(direction),0) ) end end diff --git a/bin/data/scenes/startmenu/scene.json b/bin/data/scenes/startmenu/scene.json index 1c697d5a..ec98cb20 100644 --- a/bin/data/scenes/startmenu/scene.json +++ b/bin/data/scenes/startmenu/scene.json @@ -6,14 +6,9 @@ ], "assets": [ "/gui.json", - // "./player.json", "/ui/main menu.ogg", "/gui/mainmenu/menu.json" ], - "hot reload": { - "enabled": true - }, - "clear color": [ 0, 0, 0, 1 ], "metadata": { "volumes": { "sfx": 0.25, diff --git a/client/client/ext.cpp b/client/client/ext.cpp index 1fcd15e6..16d8d488 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -133,6 +133,7 @@ void client::tick() { client::window.toggleFullscreen( false ); } // mouse move + uf::inputs::kbm::states::Mouse = {}; if ( client::config["window"]["mouse"]["center"].as() ) { auto size = client::window.getSize(); auto current = client::window.getMousePosition(); @@ -140,6 +141,12 @@ void client::tick() { client::window.setMousePosition(client::window.getSize() / 2.0f); client::window.setCursorVisible(false); + #if UF_INPUT_USE_ENUM_MOUSE + uf::inputs::kbm::states::Mouse = { + (current.x - center.x) / (float) size.x, + (current.y - center.y) / (float) size.y, + }; + #else uf::hooks.call("window:Mouse.Moved", pod::payloads::windowMouseMoved{ { { "window:Mouse.Moved", "client", }, @@ -147,6 +154,7 @@ void client::tick() { }, { center, current - center, 0 } }); + #endif } } } diff --git a/engine/inc/uf/engine/object/object.h b/engine/inc/uf/engine/object/object.h index 2372d95a..f7cf9700 100644 --- a/engine/inc/uf/engine/object/object.h +++ b/engine/inc/uf/engine/object/object.h @@ -14,6 +14,7 @@ namespace uf { public: static uf::Timer timer; static bool assertionLoad; + static bool deferLazyCalls; Object(); @@ -21,6 +22,8 @@ namespace uf { bool load( const uf::stl::string&, bool = false ); bool load( const uf::Serializer& ); + void loadAssets( const uf::Serializer& ); + uf::Object& loadChild( const uf::Serializer&, bool = true ); uf::Object* loadChildPointer( const uf::Serializer&, bool = true ); std::size_t loadChildUid( const uf::Serializer&, bool = true ); @@ -41,7 +44,12 @@ namespace uf { uf::Hooks::return_t callHook( const uf::stl::string& ); uf::Hooks::return_t callHook( const uf::stl::string&, const pod::Hook::userdata_t& ); + + uf::Hooks::return_t lazyCallHook( const uf::stl::string& ); + uf::Hooks::return_t lazyCallHook( const uf::stl::string&, const pod::Hook::userdata_t& ); + template uf::Hooks::return_t callHook( const uf::stl::string& name, const T& payload ); + template uf::Hooks::return_t lazyCallHook( const uf::stl::string& name, const T& payload ); void queueHook( const uf::stl::string&, float = 0 ); void queueHook( const uf::stl::string&, double ); diff --git a/engine/inc/uf/engine/object/object.inl b/engine/inc/uf/engine/object/object.inl index d94a4bac..53785490 100644 --- a/engine/inc/uf/engine/object/object.inl +++ b/engine/inc/uf/engine/object/object.inl @@ -34,6 +34,15 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const T& return uf::hooks.call( this->formatHookName( name ), payload ); } +template +uf::Hooks::return_t uf::Object::lazyCallHook( const uf::stl::string& name, const T& p ) { + if ( uf::Object::deferLazyCalls ) { + this->queueHook( name, p, 0.0f ); + return {}; + } + return this->callHook( name, p ); +} + template void uf::Object::queueHook( const uf::stl::string& name, const T& p, float d ) { // if ( !uf::Object::timer.running() ) uf::Object::timer.start(); diff --git a/engine/inc/uf/ext/vulkan/buffer.h b/engine/inc/uf/ext/vulkan/buffer.h index 4811746f..13e2349e 100644 --- a/engine/inc/uf/ext/vulkan/buffer.h +++ b/engine/inc/uf/ext/vulkan/buffer.h @@ -67,13 +67,7 @@ namespace ext { size_t initializeBuffer( const void*, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool = VK_DEFAULT_STAGE_BUFFERS ); bool updateBuffer( const void*, VkDeviceSize, const Buffer&, bool = VK_DEFAULT_STAGE_BUFFERS ) const; - - // template inline size_t initializeBuffer( const T* data, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (const void*) data, static_cast(sizeof(T)), usage, memoryProperties, stage ); } - // template inline size_t initializeBuffer( const T& data, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, bool stage = VK_DEFAULT_STAGE_BUFFERS ) { return initializeBuffer( (const void*) &data, static_cast(sizeof(T)), usage, memoryProperties, stage ); } - inline bool updateBuffer( const void* data, VkDeviceSize length, size_t index = 0, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( data, length, buffers.at(index), stage ); } - // template inline bool updateBuffer( const T* data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) data, static_cast(sizeof(T)), buffer, stage ); } - // template inline bool updateBuffer( const T& data, const Buffer& buffer, bool stage = VK_DEFAULT_STAGE_BUFFERS ) const { return updateBuffer( (const void*) &data, static_cast(sizeof(T)), buffer, stage ); } }; struct AccelerationStructure { diff --git a/engine/inc/uf/ext/vulkan/device.h b/engine/inc/uf/ext/vulkan/device.h index c402fe5d..da57a865 100644 --- a/engine/inc/uf/ext/vulkan/device.h +++ b/engine/inc/uf/ext/vulkan/device.h @@ -8,6 +8,18 @@ namespace ext { namespace vulkan { + enum QueueEnum { + GRAPHICS, + PRESENT, + COMPUTE, + TRANSFER, + }; + struct CommandBuffer { + bool immediate{true}; + QueueEnum queueType{QueueEnum::TRANSFER}; + VkCommandBuffer handle{VK_NULL_HANDLE}; + }; + struct UF_API Device { VkInstance instance; VkDebugUtilsMessengerEXT debugMessenger; @@ -50,14 +62,20 @@ namespace ext { uf::ThreadUnique transfer; } queues; + struct { + uf::stl::vector buffers; + uf::stl::unordered_map> commandBuffers; + } transient; + + /* + struct { + uf::stl::vector buffers; + uf::stl::unordered_map commandBuffers; + } reusable; + */ + uf::Window* window; - enum QueueEnum { - GRAPHICS, - PRESENT, - COMPUTE, - TRANSFER, - }; struct QueueFamilyIndices { uint32_t graphics; uint32_t present; @@ -69,27 +87,25 @@ namespace ext { // helpers uint32_t getQueueFamilyIndex( VkQueueFlagBits queueFlags ); uint32_t getMemoryType( uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32 *memTypeFound = nullptr ); - - VkCommandBuffer createCommandBuffer( VkCommandBufferLevel level, bool begin = true ); + VkCommandBuffer createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin = true ); + void flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queue, bool wait = false ); - void flushCommandBuffer( VkCommandBuffer commandBuffer, bool free = true ); - void flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queue, bool free = true ); + CommandBuffer fetchCommandBuffer( QueueEnum queue, bool waits = true ); + void flushCommandBuffer( CommandBuffer commandBuffer ); VkResult createBuffer( + const void* data, + VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, - VkDeviceSize size, - VkBuffer* buffer, - VkDeviceMemory *memory, - const void* data = nullptr + ext::vulkan::Buffer& buffer ); - VkResult createBuffer( - VkBufferUsageFlags usage, - VkMemoryPropertyFlags memoryProperties, - ext::vulkan::Buffer& buffer, + ext::vulkan::Buffer fetchTransientBuffer( + const void* data, VkDeviceSize size, - const void* data = nullptr + VkBufferUsageFlags usage, + VkMemoryPropertyFlags memoryProperties ); VkQueue& getQueue( QueueEnum ); diff --git a/engine/inc/uf/utils/io/inputs.h b/engine/inc/uf/utils/io/inputs.h index 8278182c..07d237e5 100644 --- a/engine/inc/uf/utils/io/inputs.h +++ b/engine/inc/uf/utils/io/inputs.h @@ -4,6 +4,8 @@ #include #include +#define UF_INPUT_USE_ENUM_MOUSE 1 + namespace uf { namespace inputs { #if UF_WINDOW_KEYCODE_STRINGS @@ -126,6 +128,7 @@ namespace uf { constexpr key_t Num9 = UF_KEY("Num9"); constexpr key_t Num0 = UF_KEY("Num0"); + constexpr key_t Mouse = UF_KEY("Mouse"); constexpr key_t Mouse1 = UF_KEY("Mouse1"); constexpr key_t Mouse2 = UF_KEY("Mouse2"); constexpr key_t Mouse3 = UF_KEY("Mouse3"); @@ -234,6 +237,7 @@ namespace uf { extern UF_API state_t Num9; extern UF_API state_t Num0; + extern UF_API analog2_t Mouse; extern UF_API state_t Mouse1; extern UF_API state_t Mouse2; extern UF_API state_t Mouse3; diff --git a/engine/src/engine/behavior/behavior.cpp b/engine/src/engine/behavior/behavior.cpp index 3083b5f4..bf775b8d 100644 --- a/engine/src/engine/behavior/behavior.cpp +++ b/engine/src/engine/behavior/behavior.cpp @@ -75,7 +75,7 @@ void uf::Behaviors::generateGraph() { std::reverse( m_graph.destroy.begin(), m_graph.destroy.end() ); } -// uf::scene::invalidateGraphs(); + uf::scene::invalidateGraphs(); } #define UF_BEHAVIOR_POLYFILL UF_BEHAVIOR_POLYFILL_GRAPH diff --git a/engine/src/engine/graph/convert.cpp b/engine/src/engine/graph/convert.cpp index 4a6b70a0..97220229 100644 --- a/engine/src/engine/graph/convert.cpp +++ b/engine/src/engine/graph/convert.cpp @@ -107,7 +107,7 @@ pod::Graph& UF_API uf::graph::convert( uf::Object& object, bool process ) { auto& graph = object.getComponent(); graph.name = object.getName(); - graph.metadata = object.getComponent()["model"]; + graph.metadata = object.getComponent()["graph"]; graph.root.entity = &object; ::process( object, graph, graph.root ); diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 0f918969..886912ed 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -462,6 +462,49 @@ void uf::graph::process( pod::Graph& graph ) { // if ( !graph.root.entity ) graph.root.entity = new uf::Object; + + // copy lighting settings from graph + auto& scene = uf::scene::getCurrentScene(); + auto& sceneMetadataJson = scene.getComponent(); +#if 1 + // merge light settings with global settings + { + const auto& globalSettings = graph.metadata["light"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( sceneMetadataJson["light"][key] ) ) return; + sceneMetadataJson["light"][key] = value; + } ); + } + // merge bloom settings with global settings + { + const auto& globalSettings = graph.metadata["light"]["bloom"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( sceneMetadataJson["light"]["bloom"][key] ) ) return; + sceneMetadataJson["light"]["bloom"][key] = value; + } ); + } + // merge shadows settings with global settings + { + const auto& globalSettings = graph.metadata["light"]["shadows"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( sceneMetadataJson["light"]["shadows"][key] ) ) return; + sceneMetadataJson["light"]["shadows"][key] = value; + } ); + } + // merge fog settings with global settings + { + const auto& globalSettings = graph.metadata["light"]["fog"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( sceneMetadataJson["light"]["fog"][key] ) ) return; + sceneMetadataJson["light"]["fog"][key] = value; + } ); + } +#endif +#if 0 + if ( ext::json::isObject(graph.metadata["assets"]) || ext::json::isArray(graph.metadata["assets"]) ) { + scene.loadAssets(graph.metadata["assets"]); + } +#endif // uf::stl::unordered_map isSrgb; @@ -490,9 +533,7 @@ void uf::graph::process( pod::Graph& graph ) { } } - auto& scene = uf::scene::getCurrentScene(); - auto& sceneMetadataJson = scene.getComponent(); - if ( !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["useLightmaps"].as(true) ) { + if ( !sceneMetadataJson["light"]["useLightmaps"].as(true) ) { graph.metadata["lights"]["lightmap"] = false; graph.metadata["baking"]["enabled"] = false; } @@ -941,10 +982,13 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) auto& childMetadataJson = child.getComponent(); auto flatten = uf::transform::flatten( node.transform ); - if ( !tag["preserve position"].as() ) childTransform.position = flatten.position; - if ( !tag["preserve orientation"].as() ) childTransform.orientation = flatten.orientation; + // if ( !tag["preserve position"].as(false) ) childTransform.position = flatten.position; + // if ( !tag["preserve orientation"].as(false) ) childTransform.orientation = flatten.orientation; + // childTransform.position = flatten.position; // childTransform.orientation = flatten.orientation; + childTransform = flatten; + // childMetadataJson["transform"] = uf::transform::encode( flatten ); } if ( tag["static"].is() ) { diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 8125f78a..c91c15df 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -36,7 +36,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { pod::payloads::assetLoad payload; payload.uid = this->getUid(); - parent.callHook("asset:Parsed.%UID%", payload); + parent.lazyCallHook("asset:Parsed.%UID%", payload); } } @@ -93,7 +93,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { auto& parent = this->getParent().as(); payload.uid = this->getUid(); - parent.callHook("asset:Parsed.%UID%", payload); + parent.lazyCallHook("asset:Parsed.%UID%", payload); } }); diff --git a/engine/src/engine/object/behaviors/graph.cpp b/engine/src/engine/object/behaviors/graph.cpp index 9c35b97d..990b5895 100644 --- a/engine/src/engine/object/behaviors/graph.cpp +++ b/engine/src/engine/object/behaviors/graph.cpp @@ -34,8 +34,8 @@ void uf::GraphBehavior::initialize( uf::Object& self ) { auto& graph = (this->getComponent() = std::move( assetLoader.get(payload.filename) )); assetLoader.remove(payload.filename); + #if 0 bool shouldUpdate = false; - auto& sceneMetadataJson = scene.getComponent(); if ( !ext::json::isNull(graph.metadata["ambient"]) ) { sceneMetadataJson["light"]["ambient"] = graph.metadata["ambient"]; @@ -54,6 +54,7 @@ void uf::GraphBehavior::initialize( uf::Object& self ) { shouldUpdate = true; } if ( shouldUpdate ) scene.callHook("object:Deserialize.%UID%"); + #endif // deferred shader loading auto& transform = this->getComponent>(); @@ -62,8 +63,8 @@ void uf::GraphBehavior::initialize( uf::Object& self ) { uf::graph::initialize( graph ); if ( graph.metadata["renderer"]["skinned"].as() ) { - if ( metadata["model"]["animation"].is() ) { - uf::graph::animate( graph, metadata["model"]["animation"].as() ); + if ( metadata["graph"]["animation"].is() ) { + uf::graph::animate( graph, metadata["graph"]["animation"].as() ); } } diff --git a/engine/src/engine/object/behaviors/loading.cpp b/engine/src/engine/object/behaviors/loading.cpp index a3730f17..dc298f46 100644 --- a/engine/src/engine/object/behaviors/loading.cpp +++ b/engine/src/engine/object/behaviors/loading.cpp @@ -73,7 +73,7 @@ void uf::LoadingBehavior::tick( uf::Object& self ) { if ( loading == loaded ) { metadata.system.loaded = true; - this->callHook("system:Load.Finished.%UID%"); + this->lazyCallHook("system:Load.Finished.%UID%"); } } void uf::LoadingBehavior::render( uf::Object& self ) {} diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index 5ee5936d..000a5a8b 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -18,6 +18,7 @@ namespace { uf::Timer uf::Object::timer(false); bool uf::Object::assertionLoad = true; +bool uf::Object::deferLazyCalls = true; UF_OBJECT_REGISTER_BEGIN(uf::Object) UF_OBJECT_REGISTER_BEHAVIOR(uf::EntityBehavior) @@ -39,6 +40,21 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name ) { uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const pod::Hook::userdata_t& payload ) { return uf::hooks.call( this->formatHookName( name ), payload ); } +uf::Hooks::return_t uf::Object::lazyCallHook( const uf::stl::string& name ) { + if ( uf::Object::deferLazyCalls ) { + this->queueHook( name, 0.0f ); + return {}; + } + return this->callHook( name ); +} +uf::Hooks::return_t uf::Object::lazyCallHook( const uf::stl::string& name, const pod::Hook::userdata_t& payload ) { + if ( uf::Object::deferLazyCalls ) { + this->queueHook( name, payload, 0.0f ); + return {}; + } + return this->callHook( name, payload ); +} + void uf::Object::queueHook( const uf::stl::string& name, double timeout ) { return queueHook( name, (float) timeout ); } @@ -147,10 +163,80 @@ bool uf::Object::reload( bool hard ) { return true; } +void uf::Object::loadAssets( const uf::Serializer& _json ){ + auto& metadata = this->getComponent(); + auto& metadataJson = this->getComponent(); + auto& scene = uf::scene::getCurrentScene(); + auto& assetLoader = scene.getComponent(); + + ext::json::Value json = _json; + + #define ASSET_ENTRY(type) { uf::string::lowercase(#type), uf::Asset::Type::type } + const uf::stl::unordered_map assets = { + ASSET_ENTRY(AUDIO), + ASSET_ENTRY(IMAGE), + ASSET_ENTRY(GRAPH), + ASSET_ENTRY(LUA), + }; + + for ( auto& pair : assets ) { + auto& assetType = pair.second; + auto& assetTypeString = pair.first; + + uf::Serializer target; + bool override = false; + if ( ext::json::isObject( json ) && ext::json::isArray( json["assets"] ) ) { + target = json["assets"]; + } else if ( ext::json::isObject( json ) && ext::json::isObject( json["assets"] ) && !ext::json::isNull( json["assets"][assetTypeString] ) ) { + target = json["assets"][assetTypeString]; + } else if ( ext::json::isArray( json ) ) { + target = json; + } else if ( ext::json::isObject( json ) && !ext::json::isNull( json[assetTypeString] ) ) { + target = json[assetTypeString]; + }/* else if ( ext::json::isObject( metadataJson["system"]["assets"] ) ) { + target = metadataJson["system"]["assets"]; + }*/ + + for ( size_t i = 0; i < target.size(); ++i ) { + bool isObject = ext::json::isObject( target[i] ); + uf::stl::string f = isObject ? target[i]["filename"].as() : target[i].as(); + uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root ); + uf::stl::string mime = isObject ? target[i]["mime"].as("") : ""; + uf::Asset::Payload payload = uf::Asset::resolveToPayload( filename, mime ); + if ( !uf::Asset::isExpected( payload, assetType ) ) continue; + payload.hash = isObject ? target[i]["hash"].as("") : ""; + payload.monoThreaded = isObject ? !target[i]["multithreaded"].as(true) : !true; + this->queueHook( "asset:QueueLoad.%UID%", payload, isObject ? target[i]["delay"].as() : 0 ); + bool bind = isObject ? target[i]["bind"].as(true) : true; + + switch ( assetType ) { + case uf::Asset::Type::LUA: { + if ( bind ) uf::instantiator::bind("LuaBehavior", *this); + } break; + case uf::Asset::Type::GRAPH: { + auto graphMetadata = json["metadata"]["graph"]; + auto& aMetadata = assetLoader.getComponent(); + aMetadata[filename] = graphMetadata; + aMetadata[filename]["root"] = json["root"]; + if ( bind ) uf::instantiator::bind("GraphBehavior", *this); + + // nasty hack to get soundscapes/music to load while the rest of the graph loads + if ( ext::json::isObject(graphMetadata["assets"]) || ext::json::isArray(graphMetadata["assets"]) ) { + scene.loadAssets(graphMetadata["assets"]); + } + } break; + } + } + } +} + bool uf::Object::load( const uf::Serializer& _json ) { auto& metadata = this->getComponent(); auto& metadataJson = this->getComponent(); + auto& scene = uf::scene::getCurrentScene(); + auto& assetLoader = scene.getComponent(); uf::Serializer json = _json; + // setup root/source/mtime if ( json["source"].is() ) { metadata.system.filename = json["source"].as(); @@ -204,8 +290,6 @@ bool uf::Object::load( const uf::Serializer& _json ) { // Basic entity information // Set name this->m_name = json["name"].is() ? json["name"].as() : json["type"].as(); - uf::Scene& scene = uf::scene::getCurrentScene(); - uf::Asset& assetLoader = scene.getComponent(); // Set transform { bool load = true; @@ -233,6 +317,15 @@ bool uf::Object::load( const uf::Serializer& _json ) { } } + // Load assets +#if 1 + { + this->loadAssets( json ); + } +#else + auto& scene = uf::scene::getCurrentScene(); + auto& assetLoader = scene.getComponent(); + #define ASSET_ENTRY(type) { uf::string::lowercase(#type), uf::Asset::Type::type } const uf::stl::unordered_map assets = { ASSET_ENTRY(AUDIO), @@ -273,13 +366,14 @@ bool uf::Object::load( const uf::Serializer& _json ) { } break; case uf::Asset::Type::GRAPH: { auto& aMetadata = assetLoader.getComponent(); - aMetadata[filename] = json["metadata"]["model"]; + aMetadata[filename] = json["metadata"]["graph"]; aMetadata[filename]["root"] = json["root"]; if ( bind ) uf::instantiator::bind("GraphBehavior", *this); } break; } } } +#endif // Bind behaviors { if ( json["type"].is() ) uf::instantiator::bind( json["type"].as(), *this ); diff --git a/engine/src/ext/imgui/imgui.cpp b/engine/src/ext/imgui/imgui.cpp index e1ec7e4d..1479188e 100644 --- a/engine/src/ext/imgui/imgui.cpp +++ b/engine/src/ext/imgui/imgui.cpp @@ -449,7 +449,7 @@ void ext::imgui::initialize() { imguiInitInfo.PhysicalDevice = uf::renderer::device.physicalDevice; imguiInitInfo.Device = uf::renderer::device.logicalDevice; imguiInitInfo.QueueFamily = uf::renderer::device.queueFamilyIndices.graphics; - imguiInitInfo.Queue = uf::renderer::device.getQueue( uf::renderer::Device::GRAPHICS ); + imguiInitInfo.Queue = uf::renderer::device.getQueue( uf::renderer::QueueEnum::GRAPHICS ); imguiInitInfo.PipelineCache = uf::renderer::device.pipelineCache; imguiInitInfo.DescriptorPool = ::descriptorPool; imguiInitInfo.Subpass = 0; @@ -463,9 +463,9 @@ void ext::imgui::initialize() { } { // Use any command queue - VkCommandBuffer commandBuffer = uf::renderer::device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::TRANSFER); + VkCommandBuffer commandBuffer = uf::renderer::device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::TRANSFER); ImGui_ImplVulkan_CreateFontsTexture(commandBuffer); - uf::renderer::device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::TRANSFER); + uf::renderer::device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::TRANSFER); ImGui_ImplVulkan_DestroyFontUploadObjects(); } diff --git a/engine/src/ext/lua/usertypes/object.cpp b/engine/src/ext/lua/usertypes/object.cpp index 97b330ae..7864876e 100644 --- a/engine/src/ext/lua/usertypes/object.cpp +++ b/engine/src/ext/lua/usertypes/object.cpp @@ -9,11 +9,64 @@ #include namespace binds { + namespace enums { + enum Components { + Metadata, + Transform, + Audio, + Asset, + Camera, + Physics, + PhysicsState, + }; + + static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{ + #define UF_LUA_REGISTER_ENUM(E) #E, enums::Components::E + ext::lua::onInitialization( []{ + auto enums = ext::lua::state.new_enum("Components", + UF_LUA_REGISTER_ENUM(Metadata), + UF_LUA_REGISTER_ENUM(Transform), + UF_LUA_REGISTER_ENUM(Audio), + UF_LUA_REGISTER_ENUM(Asset), + UF_LUA_REGISTER_ENUM(Camera), + UF_LUA_REGISTER_ENUM(Physics), + UF_LUA_REGISTER_ENUM(PhysicsState) + ); + }); + }); + } + uf::stl::string formatHookName(uf::Object& self, const uf::stl::string n ){ return self.formatHookName(n); } - sol::object getComponent( uf::Object& self, const uf::stl::string& type ) { - #define UF_LUA_RETRIEVE_COMPONENT( T )\ + sol::object getComponentFromEnum( uf::Object& self, binds::enums::Components type ) { + #define UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( E, T )\ + case enums::Components::E: return sol::make_object( ext::lua::state, std::ref(self.getComponent()) ); + + switch ( type ) { + case enums::Components::Metadata: { + self.callHook( "object:Serialize.%UID%" ); + auto& metadata = self.getComponent(); + auto decoded = ext::lua::decode( metadata ); + if ( decoded ) { + sol::table table = decoded.value(); + return sol::make_object( ext::lua::state, table ); + } + UF_MSG_ERROR("Failed to deserialize metadata for {}: {}", self.getName(), self.getUid()); + } break; + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( Transform, pod::Transform<> ); + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( Audio, uf::Audio ); + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( Asset, uf::Asset ); + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( Camera, uf::Camera ); + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( Physics, pod::Physics ); + UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( PhysicsState, pod::PhysicsState ); + } + UF_MSG_ERROR("Invalid component of {} requested for {}: {}", type, self.getName(), self.getUid()); + + return sol::make_object( ext::lua::state, sol::lua_nil ); + } + sol::object getComponentFromString( uf::Object& self, const uf::stl::string& type ) { + #define UF_LUA_RETRIEVE_COMPONENT_FROM_STRING( T )\ else if ( type == UF_NS_GET_LAST(T) ) return sol::make_object( ext::lua::state, std::ref(self.getComponent()) ); if ( type == "Metadata" ) { @@ -24,13 +77,15 @@ namespace binds { sol::table table = decoded.value(); return sol::make_object( ext::lua::state, table ); } + UF_MSG_ERROR("Failed to deserialize metadata for {}: {}", self.getName(), self.getUid()); } - UF_LUA_RETRIEVE_COMPONENT(pod::Transform<>) - UF_LUA_RETRIEVE_COMPONENT(uf::Audio) - UF_LUA_RETRIEVE_COMPONENT(uf::Asset) - UF_LUA_RETRIEVE_COMPONENT(uf::Camera) - UF_LUA_RETRIEVE_COMPONENT(pod::Physics) - UF_LUA_RETRIEVE_COMPONENT(pod::PhysicsState) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(pod::Transform<>) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(uf::Audio) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(uf::Asset) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(uf::Camera) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(pod::Physics) + UF_LUA_RETRIEVE_COMPONENT_FROM_STRING(pod::PhysicsState) + UF_MSG_ERROR("Invalid component of {} requested for {}: {}", type, self.getName(), self.getUid()); return sol::make_object( ext::lua::state, sol::lua_nil ); } void setComponent(uf::Object& self, const uf::stl::string& type, sol::object value ) { @@ -147,6 +202,10 @@ namespace binds { ext::json::Value payload = uf::Serializer(table); self.callHook( name, payload ); } + void lazyCallHook( uf::Object& self, const uf::stl::string& name, sol::table table = ext::lua::createTable() ) { + ext::json::Value payload = uf::Serializer(table); + self.lazyCallHook( name, payload ); + } void queueHook( uf::Object& self, const uf::stl::string& name, sol::table table, float delay = 0.0f ) { ext::json::Value payload = uf::Serializer(table); self.queueHook( name, payload, delay ); @@ -159,6 +218,7 @@ namespace binds { uf::stl::string getName( const uf::Object& o ) { return o.getName(); } } + UF_LUA_REGISTER_USERTYPE(uf::Object, sol::call_constructor, sol::initializers( []( uf::Object& self, sol::object arg, bool init = true ){ @@ -177,7 +237,8 @@ UF_LUA_REGISTER_USERTYPE(uf::Object, UF_LUA_REGISTER_USERTYPE_DEFINE( uid, UF_LUA_C_FUN(::binds::getUid) ), UF_LUA_REGISTER_USERTYPE_DEFINE( name, UF_LUA_C_FUN(::binds::getName) ), UF_LUA_REGISTER_USERTYPE_DEFINE( formatHookName, UF_LUA_C_FUN(::binds::formatHookName) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponent) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromEnum) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromString) ), UF_LUA_REGISTER_USERTYPE_DEFINE( setComponent, UF_LUA_C_FUN(::binds::setComponent) ), UF_LUA_REGISTER_USERTYPE_DEFINE( bind, UF_LUA_C_FUN(::binds::bind) ), UF_LUA_REGISTER_USERTYPE_DEFINE( findByUid, UF_LUA_C_FUN(::binds::findByUid) ), @@ -189,46 +250,8 @@ UF_LUA_REGISTER_USERTYPE(uf::Object, UF_LUA_REGISTER_USERTYPE_DEFINE( getParent, UF_LUA_C_FUN(::binds::getParent) ), UF_LUA_REGISTER_USERTYPE_DEFINE( addHook, UF_LUA_C_FUN(::binds::addHook) ), UF_LUA_REGISTER_USERTYPE_DEFINE( callHook, UF_LUA_C_FUN(::binds::callHook) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( lazyCallHook, UF_LUA_C_FUN(::binds::lazyCallHook) ), UF_LUA_REGISTER_USERTYPE_DEFINE( queueHook, UF_LUA_C_FUN(::binds::queueHook) ), UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::toString) ) ) -/* -namespace { - static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{ - ext::lua::onInitialization( []{ - ext::lua::state.new_usertype(UF_NS_GET_LAST(uf::Object), - sol::call_constructor, sol::initializers( []( uf::Object& self, sol::object arg, bool init = true ){ - if ( arg.is() ) { - self.load( arg.as() ); - } else if ( arg.is() ) { - auto encoded = ext::lua::encode( arg.as() ); - if ( encoded ) { - uf::Serializer json = encoded.value(); - self.load(json); - } - } - if ( init ) self.initialize(); - }), - "uid", UF_LUA_C_FUN(::binds::getUid), - "name", UF_LUA_C_FUN(::binds::getName), - "formatHookName", UF_LUA_C_FUN(::binds::formatHookName), - "getComponent", UF_LUA_C_FUN(::binds::getComponent), - "setComponent", UF_LUA_C_FUN(::binds::setComponent), - "bind", UF_LUA_C_FUN(::binds::bind), - "findByUid", UF_LUA_C_FUN(::binds::findByUid), - "findByName", UF_LUA_C_FUN(::binds::findByName), - "addChild", UF_LUA_C_FUN(::binds::addChild), - "removeChild", UF_LUA_C_FUN(::binds::removeChild), - "loadChild", UF_LUA_C_FUN(::binds::loadChild), - "getChildren", UF_LUA_C_FUN(::binds::getChildren), - "getParent", UF_LUA_C_FUN(::binds::getParent), - "addHook", UF_LUA_C_FUN(::binds::addHook), - "callHook", UF_LUA_C_FUN(::binds::callHook), - "queueHook", UF_LUA_C_FUN(::binds::queueHook), - "__tostring", UF_LUA_C_FUN(::binds::toString) - ); - }); - }); -} -*/ #endif \ No newline at end of file diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index 0e6e4917..18f28eb7 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -446,7 +446,7 @@ void ext::openvr::submit() { bool invert = swapEyes; vulkanData.m_pDevice = ( VkDevice_T * ) uf::renderer::device; vulkanData.m_pPhysicalDevice = ( VkPhysicalDevice_T * ) uf::renderer::device.physicalDevice; vulkanData.m_pInstance = ( VkInstance_T *) uf::renderer::device.instance; - vulkanData.m_pQueue = ( VkQueue_T * ) uf::renderer::device.getQueue( uf::renderer::Device::QueueEnum::PRESENT ); + vulkanData.m_pQueue = ( VkQueue_T * ) uf::renderer::device.getQueue( uf::renderer::QueueEnum::PRESENT ); vulkanData.m_nQueueFamilyIndex = uf::renderer::device.queueFamilyIndices.present; vulkanData.m_nWidth = width; diff --git a/engine/src/ext/vulkan/buffer.cpp b/engine/src/ext/vulkan/buffer.cpp index e301ed17..77018b40 100644 --- a/engine/src/ext/vulkan/buffer.cpp +++ b/engine/src/ext/vulkan/buffer.cpp @@ -129,10 +129,11 @@ void ext::vulkan::Buffer::initialize( const void* data, VkDeviceSize length, VkB if ( !device ) device = &ext::vulkan::device; if ( stage ) usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; // implicitly set properties VK_CHECK_RESULT(device->createBuffer( + nullptr, + length, usage, memoryProperties, - *this, - length + *this )); if ( data && length ) update( data, length, stage ); } @@ -157,26 +158,37 @@ bool ext::vulkan::Buffer::update( const void* data, VkDeviceSize length, bool st return false; } - Buffer staging; - ext::vulkan::Device* device = this->device ? this->device : &ext::vulkan::device; +#if 1 + Buffer staging = device->fetchTransientBuffer( + data, + length, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + ); + VkCommandBuffer copyCommand = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::TRANSFER); + VkBufferCopy region = {}; + region.size = length; + vkCmdCopyBuffer(copyCommand, staging.buffer, buffer, 1, ®ion); + device->flushCommandBuffer(copyCommand, QueueEnum::TRANSFER); +#else + Buffer staging; device->createBuffer( + data, + length, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - staging, - length, - data + staging ); - // Copy to staging buffer - VkCommandBuffer copyCommand = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::TRANSFER); - VkBufferCopy region = {}; - region.size = length; - vkCmdCopyBuffer(copyCommand, staging.buffer, buffer, 1, ®ion); - - device->flushCommandBuffer(copyCommand, Device::QueueEnum::TRANSFER); + VkCommandBuffer copyCommand = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::TRANSFER); + VkBufferCopy region = {}; + region.size = length; + vkCmdCopyBuffer(copyCommand, staging.buffer, buffer, 1, ®ion); + device->flushCommandBuffer(copyCommand, QueueEnum::TRANSFER); staging.destroy(); +#endif return false; } diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index e4e2cf6f..5a873551 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -555,9 +555,6 @@ uint32_t ext::vulkan::Device::getMemoryType( uint32_t typeBits, VkMemoryProperty UF_EXCEPTION("Vulkan error: could not find a matching memory type"); } -VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel level, bool begin ){ - return createCommandBuffer( level, QueueEnum::TRANSFER, begin ); -} VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel level, QueueEnum queue, bool begin ){ VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( getCommandPool(queue), level, 1 ); @@ -570,11 +567,7 @@ VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel l } return commandBuffer; } - -void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, bool wait ) { - return flushCommandBuffer( commandBuffer, QueueEnum::TRANSFER, wait ); -} -void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queueType, bool wait ) { +void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, QueueEnum queueType, bool immediate ) { if ( commandBuffer == VK_NULL_HANDLE ) return; VK_CHECK_RESULT( vkEndCommandBuffer( commandBuffer ) ); @@ -585,56 +578,54 @@ void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, Que auto& queue = getQueue( queueType ); VK_CHECK_RESULT(vkQueueSubmit( queue, 1, &submitInfo, VK_NULL_HANDLE)); - if ( wait ) { + + if ( immediate ) { VK_CHECK_RESULT(vkQueueWaitIdle( queue )); vkFreeCommandBuffers(logicalDevice, getCommandPool( queueType ), 1, &commandBuffer); + } else { + this->transient.commandBuffers[queueType].emplace_back(commandBuffer); } } +ext::vulkan::CommandBuffer ext::vulkan::Device::fetchCommandBuffer( ext::vulkan::QueueEnum queueType, bool immediate ){ + return { + .immediate = immediate, + .queueType = queueType, + .handle = this->createCommandBuffer( VK_COMMAND_BUFFER_LEVEL_PRIMARY, queueType, true ), + }; #if 0 -VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, VkDeviceSize size, VkBuffer* buffer, VkDeviceMemory* memory, const void* data ) { - // Create the buffer handle - VkBufferCreateInfo bufferCreateInfo = ext::vulkan::initializers::bufferCreateInfo(usage, size); - bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VK_CHECK_RESULT( vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, buffer)); - - // Create the memory backing up the buffer handle - VkMemoryRequirements memReqs; - VkMemoryAllocateInfo memAlloc = ext::vulkan::initializers::memoryAllocateInfo(); - vkGetBufferMemoryRequirements(logicalDevice, *buffer, &memReqs); - memAlloc.allocationSize = memReqs.size; - // Find a memory type index that fits the properties of the buffer - memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryProperties); - - VK_CHECK_RESULT( vkAllocateMemory(logicalDevice, &memAlloc, nullptr, memory)); - - // If a pointer to the buffer data has been passed, map the buffer and copy over the data - if ( data != nullptr ) { - void *mapped; - VK_CHECK_RESULT(vkMapMemory(logicalDevice, *memory, 0, size, 0, &mapped)); - - memcpy(mapped, data, size); - // If host coherency hasn't been requested, do a manual flush to make writes visible - if ( (memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0 ) { - VkMappedMemoryRange mappedRange = ext::vulkan::initializers::mappedMemoryRange(); - mappedRange.memory = *memory; - mappedRange.offset = 0; - mappedRange.size = size; - vkFlushMappedMemoryRanges(logicalDevice, 1, &mappedRange); - } - vkUnmapMemory(logicalDevice, *memory); + if ( transient ) { + ext::vulkan::CommandBuffer commandBuffer; + commandBuffer.waits = waits; + commandBuffer.queueType = queueType; + commandBuffer.handle = this->createCommandBuffer( VK_COMMAND_BUFFER_LEVEL_PRIMARY, queueType, true ); + return; } - // Attach the memory to the buffer object - VK_CHECK_RESULT(vkBindBufferMemory(logicalDevice, *buffer, *memory, 0)); - return VK_SUCCESS; -} +// bool exists = this->reusable.commandBuffers.count( queueType ) > 0; + auto& commandBuffer = this->reusable.commandBuffers[queueType]; +// if ( !exists ) { + if ( commandBuffer.handle == VK_NULL_HANDLE ) { + commandBuffer.state = 1; + commandBuffer.handle = this->createCommandBuffer( VK_COMMAND_BUFFER_LEVEL_PRIMARY, queueType, true ); + return commandBuffer; + } + if ( commandBuffer.state == 0 ) { + commandBuffer.state = 1; + VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo(); + VK_CHECK_RESULT( vkBeginCommandBuffer( commandBuffer.handle, &cmdBufInfo ) ); + } + return commandBuffer; #endif +} +void ext::vulkan::Device::flushCommandBuffer( ext::vulkan::CommandBuffer commandBuffer ) { + return this->flushCommandBuffer( commandBuffer.handle, commandBuffer.queueType, commandBuffer.immediate ); +} VkResult ext::vulkan::Device::createBuffer( + const void* data, + VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memoryProperties, - ext::vulkan::Buffer& buffer, - VkDeviceSize size, - const void* data + ext::vulkan::Buffer& buffer ) { buffer.device = this; buffer.usage = usage; @@ -657,13 +648,23 @@ VkResult ext::vulkan::Device::createBuffer( // Attach the memory to the buffer object return buffer.bind(); } -VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum) { +ext::vulkan::Buffer ext::vulkan::Device::fetchTransientBuffer( + const void* data, + VkDeviceSize size, + VkBufferUsageFlags usage, + VkMemoryPropertyFlags memoryProperties +) { + auto& buffer = this->transient.buffers.emplace_back(); + VK_CHECK_RESULT(this->createBuffer(data, size, usage, memoryProperties, buffer)); + return buffer.alias(); +} +VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::QueueEnum queueEnum) { return this->getCommandPool( queueEnum, std::this_thread::get_id() ); } -VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) { +VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::QueueEnum queueEnum ) { return this->getQueue( queueEnum, std::this_thread::get_id() ); } -VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) { +VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::QueueEnum queueEnum, std::thread::id id ) { uint32_t index = 0; VkCommandPool* pool = NULL; bool exists = false; @@ -701,7 +702,7 @@ VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEn } return *pool; } -VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) { +VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::QueueEnum queueEnum, std::thread::id id ) { uint32_t index = 0; VkQueue* queue = NULL; bool exists = false; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 287d7b08..1009045b 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -1357,7 +1357,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() { scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment; scratchBuffer.update( NULL, maxScratchBufferSize ); - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::COMPUTE); for ( auto& blasData : blasDatas ) { blasData.as.buffer = this->buffers[blasBufferIndex].alias(); blasData.as.buffer.descriptor.offset = blasBufferOffset; @@ -1402,7 +1402,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() { queryCount++ ); } - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::COMPUTE); } // compact if ( queryPool ) { @@ -1426,7 +1426,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() { this->buffers[blasBufferIndex].swap(oldBuffer); size_t blasBufferOffset{}; - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::COMPUTE); for ( auto& blasData : blasDatas ) { blasData.as.buffer = this->buffers[blasBufferIndex].alias(); blasData.as.buffer.descriptor.offset = blasBufferOffset; @@ -1452,7 +1452,7 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() { uf::renderer::vkCmdCopyAccelerationStructureKHR(commandBuffer, ©Info); } - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::COMPUTE); oldBuffer.destroy(); } @@ -1644,7 +1644,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{countInstance, 0, 0, 0}; const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo = &buildOffsetInfo; - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::COMPUTE); uf::renderer::vkCmdBuildAccelerationStructuresKHR( commandBuffer, 1, @@ -1661,7 +1661,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect 0 ); - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::COMPUTE); } #if TLAS_FRONT_AND_BACK @@ -1671,9 +1671,9 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect copyInfo.dst = tlasBack.handle; copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR; - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::COMPUTE); uf::renderer::vkCmdCopyAccelerationStructureKHR(commandBuffer, ©Info); - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::COMPUTE); } #endif @@ -1711,9 +1711,9 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect copyInfo.dst = tlas.handle; copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR; - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::COMPUTE); uf::renderer::vkCmdCopyAccelerationStructureKHR(commandBuffer, ©Info); - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::COMPUTE); uf::renderer::vkDestroyAccelerationStructureKHR(device, cleanup.handle, nullptr); oldBuffer.destroy(); diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index 3b8b21ff..f47f8568 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -77,7 +77,7 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layer VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo)); VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory; - VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED @@ -162,7 +162,7 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layer imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; imageMemoryBarrier.newLayout = attachment.descriptor.layout; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - device->flushCommandBuffer(copyCmd, Device::QueueEnum::GRAPHICS); + device->flushCommandBuffer(copyCmd, QueueEnum::GRAPHICS); const uint8_t* data; vmaMapMemory( allocator, allocation, (void**)&data ); @@ -220,7 +220,7 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma commands.resize( swapchain.buffers ); VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( - device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS), + device->getCommandPool(this->getType() == "Compute" ? QueueEnum::COMPUTE : QueueEnum::GRAPHICS), VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast(commands.size()) ); @@ -245,7 +245,7 @@ void ext::vulkan::RenderMode::cleanupAllCommands() { auto& container = this->commands.container(); for ( auto& pair : container ) { if ( pair.second.empty() ) continue; - vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); + vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? QueueEnum::COMPUTE : QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); pair.second.clear(); } container.clear(); @@ -255,7 +255,7 @@ void ext::vulkan::RenderMode::cleanupCommands( std::thread::id id ) { for ( auto& pair : container ) { if ( pair.first == id ) continue; if ( pair.second.empty() ) continue; - vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); + vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? QueueEnum::COMPUTE : QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); pair.second.clear(); } this->commands.cleanup( id ); @@ -379,7 +379,7 @@ void ext::vulkan::RenderMode::destroy() { for ( auto& pair : this->commands.container() ) { if ( !pair.second.empty() ) { - vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); + vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? QueueEnum::COMPUTE : QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); } pair.second.clear(); } diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index de275574..a1f70177 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -240,14 +240,14 @@ void ext::vulkan::BaseRenderMode::render() { submitInfo.commandBufferCount = 1; // Submit to the graphics queue passing a wait fence - VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); //vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]); // Present the current buffer to the swap chain // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation // This ensures that the image is not presented to the windowing system until all commands have been submitted - VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore)); - VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT ))); + VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore)); + VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( QueueEnum::PRESENT ))); this->executed = true; @@ -474,7 +474,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { } #if 0 if ( true ) { - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::TRANSFER); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::QueueEnum::TRANSFER); for ( size_t i = 0; i < images.size(); ++i ) { VkImageMemoryBarrier imageMemoryBarrier = {}; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; @@ -496,7 +496,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); } - device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::TRANSFER); + device.flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::TRANSFER); } #endif /* diff --git a/engine/src/ext/vulkan/rendermodes/compute.cpp b/engine/src/ext/vulkan/rendermodes/compute.cpp index 46747ea8..a5a17872 100644 --- a/engine/src/ext/vulkan/rendermodes/compute.cpp +++ b/engine/src/ext/vulkan/rendermodes/compute.cpp @@ -210,7 +210,7 @@ void ext::vulkan::ComputeRenderMode::render() { submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( uf::renderer::Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( uf::renderer::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer])); if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} ); diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index ec0f1d97..092f3da2 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -522,7 +522,7 @@ void ext::vulkan::DeferredRenderMode::render() { submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} ); diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 22b4150c..8b16501e 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -353,6 +353,15 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } } } else if ( metadata.type != uf::renderer::settings::pipelines::names::rt ) { + /* + auto previousTextures = std::move(blitter.material.textures); + blitter.material.textures.clear(); + auto& shader = blitter.material.getShader("fragment"); + for ( auto& prevTex : previousTextures ) { + shader.textures.emplace_back(prevTex); + } + */ + for ( auto& attachment : renderTarget.attachments ) { if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; @@ -458,7 +467,7 @@ void ext::vulkan::RenderTargetRenderMode::render() { submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission) submitInfo.commandBufferCount = 1; - VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer])); if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} ); diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index 28387488..1daeb242 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -528,7 +528,7 @@ void ext::vulkan::Texture::fromBuffers( subresourceRange.levelCount = this->mips; subresourceRange.layerCount = this->layers; - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); setImageLayout( commandBuffer, image, @@ -536,7 +536,7 @@ void ext::vulkan::Texture::fromBuffers( imageLayout, subresourceRange ); - device.flushCommandBuffer(commandBuffer, Device::QueueEnum::GRAPHICS); + device.flushCommandBuffer(commandBuffer, QueueEnum::GRAPHICS); this->imageLayout = imageLayout; } @@ -575,7 +575,7 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3 VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &image, &allocation, &allocationInfo)); deviceMemory = allocationInfo.deviceMemory; - VkCommandBuffer layoutCmd = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer layoutCmd = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); imageLayout = VK_IMAGE_LAYOUT_GENERAL; setImageLayout( @@ -587,7 +587,7 @@ void ext::vulkan::Texture::asRenderTarget( Device& device, uint32_t width, uint3 this->mips ); - device.flushCommandBuffer(layoutCmd, Device::QueueEnum::GRAPHICS); + device.flushCommandBuffer(layoutCmd, QueueEnum::GRAPHICS); // Create sampler // sampler.initialize( device ); @@ -702,17 +702,16 @@ void ext::vulkan::Texture::update( void* data, VkDeviceSize bufferSize, VkImageL bufferCopyRegion.imageExtent.depth = depth; bufferCopyRegion.bufferOffset = 0; // - Buffer staging; - VK_CHECK_RESULT(device.createBuffer( - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - staging, +#if 1 + Buffer staging = device.fetchTransientBuffer( + data, bufferSize, - data - )); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + ); // Use a separate command buffer for texture loading - VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy @@ -741,9 +740,51 @@ void ext::vulkan::Texture::update( void* data, VkDeviceSize bufferSize, VkImageL subresourceRange ); - device.flushCommandBuffer(commandBuffer, Device::QueueEnum::GRAPHICS); + device.flushCommandBuffer(commandBuffer, QueueEnum::GRAPHICS); +#else + Buffer staging; + VK_CHECK_RESULT(device.createBuffer( + data, + bufferSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + staging + )); + + // Use a separate command buffer for texture loading + VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); + + // Image barrier for optimal image (target) + // Optimal image will be used as destination for the copy + setImageLayout( + commandBuffer, + image, + imageLayout, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + subresourceRange + ); + // Copy mip levels from staging buffer + vkCmdCopyBufferToImage( + commandBuffer, + staging.buffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &bufferCopyRegion + ); + if ( this->mips > 1 ) this->generateMipmaps(commandBuffer, layer); + setImageLayout( + commandBuffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + targetImageLayout, + subresourceRange + ); + + device.flushCommandBuffer(commandBuffer, QueueEnum::GRAPHICS); // Clean up staging resources staging.destroy(); +#endif this->imageLayout = targetImageLayout; @@ -867,7 +908,7 @@ uf::Image ext::vulkan::Texture2D::screenshot( uint32_t layerID ) { VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo)); VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory; - VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED @@ -934,7 +975,7 @@ uf::Image ext::vulkan::Texture2D::screenshot( uint32_t layerID ) { imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; imageMemoryBarrier.newLayout = descriptor.imageLayout; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - device->flushCommandBuffer(copyCmd, Device::QueueEnum::GRAPHICS); + device->flushCommandBuffer(copyCmd, QueueEnum::GRAPHICS); const uint8_t* data; vmaMapMemory( allocator, allocation, (void**)&data ); @@ -975,7 +1016,7 @@ uf::Image ext::vulkan::Texture3D::screenshot( uint32_t layerID ) { VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo)); VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory; - VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, Device::QueueEnum::GRAPHICS); + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, QueueEnum::GRAPHICS); VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED @@ -1047,7 +1088,7 @@ uf::Image ext::vulkan::Texture3D::screenshot( uint32_t layerID ) { imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; imageMemoryBarrier.newLayout = descriptor.imageLayout; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); - device->flushCommandBuffer(copyCmd, Device::QueueEnum::GRAPHICS); + device->flushCommandBuffer(copyCmd, QueueEnum::GRAPHICS); const uint8_t* data; vmaMapMemory( allocator, allocation, (void**)&data ); diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 169bb70d..3b5efd47 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -436,6 +436,45 @@ void ext::vulkan::tick() { void ext::vulkan::render() { ext::vulkan::mutex.lock(); + // process in-flight resources + { + // cleanup in-flight commands + for ( auto& pair : device.transient.commandBuffers ) { + auto queueType = pair.first; + auto& commandBuffers = pair.second; + + auto& queue = device.getQueue( queueType ); + auto& commandPool = device.getCommandPool( queueType ); + + VK_CHECK_RESULT(vkQueueWaitIdle( queue )); + vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data()); + + commandBuffers.clear(); + } + // cleanup in-flight buffers + for ( auto& buffer : device.transient.buffers ) { + buffer.destroy(); + } + device.transient.buffers.clear(); + } +#if 0 + // process reusable commands + { + for ( auto& pair : device.reusable.commandBuffers ) { + auto queueType = pair.first; + auto& cb = pair.second; + auto& commandBuffer = cb.commandBuffer; + + auto& queue = device.getQueue( queueType ); + auto& commandPool = device.getCommandPool( queueType ); + + VK_CHECK_RESULT(vkQueueWaitIdle( queue )); + vkResetCommandBuffer(device, commandPool, 1, &commandBuffer); + cb.state = 0; + } + } +#endif + if ( settings::experimental::batchQueueSubmissions ) { uf::stl::vector auxRenderModes; auxRenderModes.reserve( renderModes.size() ); uf::stl::vector specialRenderModes; specialRenderModes.reserve( renderModes.size() ); @@ -476,12 +515,12 @@ void ext::vulkan::render() { if ( !submitsCompute.empty() ) { VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesCompute[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT)); VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesCompute[states::currentBuffer])); - VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( Device::QueueEnum::COMPUTE ), submitsCompute.size(), submitsCompute.data(), ::auxFencesCompute[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::COMPUTE ), submitsCompute.size(), submitsCompute.data(), ::auxFencesCompute[states::currentBuffer])); } if ( !submitsGraphics.empty() ) { VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFencesGraphics[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT)); VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFencesGraphics[states::currentBuffer])); - VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( Device::QueueEnum::GRAPHICS ), submitsGraphics.size(), submitsGraphics.data(), ::auxFencesGraphics[states::currentBuffer])); + VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( QueueEnum::GRAPHICS ), submitsGraphics.size(), submitsGraphics.data(), ::auxFencesGraphics[states::currentBuffer])); } } // stuff we can't batch diff --git a/engine/src/utils/io/inputs.cpp b/engine/src/utils/io/inputs.cpp index 6c5b839f..a5c9c588 100644 --- a/engine/src/utils/io/inputs.cpp +++ b/engine/src/utils/io/inputs.cpp @@ -102,6 +102,7 @@ uf::inputs::state_t uf::inputs::kbm::states::Num8 = false; uf::inputs::state_t uf::inputs::kbm::states::Num9 = false; uf::inputs::state_t uf::inputs::kbm::states::Num0 = false; +uf::inputs::analog2_t uf::inputs::kbm::states::Mouse = {}; uf::inputs::state_t uf::inputs::kbm::states::Mouse1 = false; uf::inputs::state_t uf::inputs::kbm::states::Mouse2 = false; uf::inputs::state_t uf::inputs::kbm::states::Mouse3 = false; @@ -280,7 +281,8 @@ uf::inputs::analog_t uf::inputs::analog( const uf::stl::string& key ) { return 0.0; } uf::inputs::analog2_t uf::inputs::analog2( const uf::stl::string& key ) { - if ( key == uf::inputs::controller::enums::L_JOYSTICK ) return uf::inputs::controller::states::L_JOYSTICK; + if ( key == uf::inputs::kbm::enums::Mouse ) return uf::inputs::kbm::states::Mouse; + else if ( key == uf::inputs::controller::enums::L_JOYSTICK ) return uf::inputs::controller::states::L_JOYSTICK; else if ( key == uf::inputs::controller::enums::R_JOYSTICK ) return uf::inputs::controller::states::R_JOYSTICK; return {}; diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 17fd6bdb..330897d3 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -56,7 +56,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) { #if UF_USE_OPENGL metadataJson["light"]["shadows"] = false; #endif - if ( !sceneMetadata["system"]["config"]["engine"]["scenes"]["shadows"]["enabled"].as(true) ) + if ( !sceneMetadata["light"]["shadows"]["enabled"].as(true) ) metadataJson["light"]["shadows"] = false; if ( metadataJson["light"]["shadows"].as() ) { auto& cameraTransform = camera.getTransform(); @@ -259,18 +259,21 @@ void ext::LightBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& } void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ /*this->*/color = uf::vector::decode( serializer["light"]["color"], /*this->*/color ); - /*this->*/power = serializer["light"]["power"].as(/*this->*/power); - /*this->*/bias = serializer["light"]["bias"]["shader"].as(/*this->*/bias); - /*this->*/shadows = serializer["light"]["shadows"].as(/*this->*/shadows); - /*this->*/global = serializer["light"]["global"].as(/*this->*/global); - /*this->*/renderer.mode = serializer["system"]["renderer"]["mode"].as(/*this->*/renderer.mode); + /*this->*/power = serializer["light"]["power"].as(/*this->*/power); + /*this->*/bias = serializer["light"]["bias"]["shader"].as(/*this->*/bias); + /*this->*/shadows = serializer["light"]["shadows"].as(/*this->*/shadows); + /*this->*/global = serializer["light"]["global"].as(/*this->*/global); + /*this->*/renderer.mode = serializer["system"]["renderer"]["mode"].as(/*this->*/renderer.mode); // /*this->*/renderer.rendered = false; - /*this->*/renderer.external = serializer["light"]["external update"].as(/*this->*/renderer.external); + /*this->*/renderer.external = serializer["light"]["external update"].as(/*this->*/renderer.external); // /*this->*/renderer.limiter = serializer["system"]["renderer"]["timer"].as(/*this->*/renderer.limiter); + if ( serializer["light"]["type"].is() ) { - /*this->*/type = serializer["light"]["type"].as(/*this->*/type); + /*this->*/type = serializer["light"]["type"].as(/*this->*/type); if ( serializer["light"]["dynamic"].as() ) /*this->*/type = -/*this->*/type; + } else if ( serializer["light"]["type"].is() ) { + uf::stl::string lightType = serializer["light"]["type"].as(); if ( lightType == "point" ) /*this->*/type = 1; else if ( lightType == "spot" ) /*this->*/type = 2; diff --git a/ext/behaviors/player/behavior.cpp b/ext/behaviors/player/behavior.cpp index fce4714b..fcde25be 100644 --- a/ext/behaviors/player/behavior.cpp +++ b/ext/behaviors/player/behavior.cpp @@ -81,16 +81,18 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) { }); // Rotate Camera +#if !UF_INPUT_USE_ENUM_MOUSE this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload ){ const pod::Vector2ui deadZone{0, 0}; if ( (payload.mouse.delta.x == 0 && payload.mouse.delta.y == 0) || !metadata.system.control ) return; - + pod::Vector2f delta = { (float) metadata.mouse.sensitivity.x * (abs(payload.mouse.delta.x) < deadZone.x ? 0 : payload.mouse.delta.x) / payload.window.size.x, (float) metadata.mouse.sensitivity.y * (abs(payload.mouse.delta.y) < deadZone.y ? 0 : payload.mouse.delta.y) / payload.window.size.y }; metadata.camera.queued += delta; }); +#endif #if UF_USE_DISCORD // Discord Integration @@ -232,13 +234,13 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { payload["user"] = this->getUid(); payload["uid"] = pointer->getUid(); payload["depth"] = uf::vector::norm(direction * depth); - pointer->callHook( "entity:Use.%UID%", payload ); + pointer->lazyCallHook( "entity:Use.%UID%", payload ); } else { payload["user"] = this->getUid(); payload["uid"] = 0; payload["depth"] = -1; } - this->callHook( "entity:Use.%UID%", payload ); + this->lazyCallHook( "entity:Use.%UID%", payload ); /* auto& emitter = this->getComponent(); uf::stl::string filename = pointer ? "./ui/select.ogg" : "./ui/deny.ogg"; @@ -384,6 +386,22 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { metadata.system.crouching = false; } + // + #if UF_INPUT_USE_ENUM_MOUSE + { + const pod::Vector2ui deadZone{0, 0}; + const auto& mouseDelta = uf::inputs::kbm::states::Mouse; + bool shouldnt = (mouseDelta.x == 0 && mouseDelta.y == 0) || !metadata.system.control; + if ( !shouldnt ) { + pod::Vector2f delta = { + (float) metadata.mouse.sensitivity.x * (abs(mouseDelta.x) < deadZone.x ? 0 : mouseDelta.x), + (float) metadata.mouse.sensitivity.y * (abs(mouseDelta.y) < deadZone.y ? 0 : mouseDelta.y) + }; + metadata.camera.queued += delta; + } + } + #endif + if ( metadata.camera.queued.x != 0 || metadata.camera.queued.y != 0 ) { auto lookDelta = metadata.camera.queued; if ( abs(lookDelta.x) > uf::physics::time::delta / metadata.mouse.smoothing.x ) lookDelta.x *= uf::physics::time::delta * metadata.mouse.smoothing.x; diff --git a/ext/behaviors/player/model/behavior.cpp b/ext/behaviors/player/model/behavior.cpp index a5ce4ee7..1bcafcca 100644 --- a/ext/behaviors/player/model/behavior.cpp +++ b/ext/behaviors/player/model/behavior.cpp @@ -67,8 +67,8 @@ void ext::PlayerModelBehavior::Metadata::serialize( uf::Object& self, uf::Serial void ext::PlayerModelBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ auto& transform = this->getComponent>(); - /*this->*/track = serializer["track"].as(); - /*this->*/hide = serializer["hide"].as(); + /*this->*/track = serializer["track"].as(/*this->*/track); + /*this->*/hide = serializer["hide"].as(/*this->*/hide); /*this->*/scale = transform.scale; /*this->*/set = false; diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp index 950e101e..226c5e66 100644 --- a/ext/behaviors/raytrace/behavior.cpp +++ b/ext/behaviors/raytrace/behavior.cpp @@ -16,6 +16,10 @@ #include "../light/behavior.h" #include "../scene/behavior.h" +namespace { + uf::renderer::Texture emptyTexture; +} + UF_BEHAVIOR_REGISTER_CPP(ext::RayTraceSceneBehavior) UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = true) #define this (&self) @@ -40,6 +44,20 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) { uf::renderer::addRenderMode( renderMode, "Compute" ); } + { + uf::stl::vector pixels = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + ::emptyTexture.sampler.descriptor.filter.min = VK_FILTER_NEAREST; + ::emptyTexture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST; + ::emptyTexture.fromBuffers( (void*) &pixels[0], pixels.size(), ext::vulkan::enums::Format::R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL ); + + auto& renderMode = uf::renderer::getRenderMode("Compute", true); + auto& blitter = *renderMode.getBlitter(); + blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture ); + } + UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson); } void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { @@ -51,12 +69,14 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { static uf::stl::vector previousGraphics; uf::stl::vector graphics; - this->process([&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; + auto& scene = uf::scene::getCurrentScene(); + auto& graph = scene.getGraph(); + for ( auto entity : graph ) { + if ( !entity->hasComponent() ) continue; auto& graphic = entity->getComponent(); - if ( graphic.accelerationStructures.bottoms.empty() ) return; + if ( graphic.accelerationStructures.bottoms.empty() ) continue; graphics.emplace_back(&graphic); - }); + } if ( graphics.empty() ) return; bool update = false; @@ -168,7 +188,8 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { auto& blitter = *renderMode.getBlitter(); if ( blitter.material.hasShader("fragment") ) { auto& shader = blitter.material.getShader("fragment"); - if ( shader.textures.empty() ) { + if ( shader.textures.empty() || ( !shader.textures.empty() && shader.textures.front().image == ::emptyTexture.image ) ) { + shader.textures.clear(); auto& tex = shader.textures.emplace_back(); tex.aliasTexture( image ); diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 229fed3c..9b667b65 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -596,7 +596,6 @@ void ext::ExtSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serialize serializer["light"]["should"] = /*this->*/light.enabled; serializer["light"]["ambient"] = uf::vector::encode( /*this->*/light.ambient ); - serializer["light"]["specular"] = uf::vector::encode( /*this->*/light.specular ); serializer["light"]["exposure"] = /*this->*/light.exposure; serializer["light"]["gamma"] = /*this->*/light.gamma; serializer["light"]["brightnessThreshold"] = /*this->*/light.brightnessThreshold; @@ -618,49 +617,84 @@ void ext::ExtSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serialize serializer["system"]["renderer"]["shader"]["parameters"] = uf::vector::encode( /*this->*/shader.parameters ); } void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) { - /*this->*/max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as(/*this->*/max.textures2D); - /*this->*/max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as(/*this->*/max.texturesCube); - /*this->*/max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as(/*this->*/max.textures3D); + // merge light settings with global settings + { + const auto& globalSettings = ext::config["engine"]["scenes"]["lights"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( serializer["light"][key] ) ) return; + serializer["light"][key] = value; + } ); + } + // merge bloom settings with global settings + { + const auto& globalSettings = ext::config["engine"]["scenes"]["lights"]["bloom"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( serializer["light"]["bloom"][key] ) ) return; + serializer["light"]["bloom"][key] = value; + } ); + } + // merge shadows settings with global settings + { + const auto& globalSettings = ext::config["engine"]["scenes"]["lights"]["shadows"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( serializer["light"]["shadows"][key] ) ) return; + serializer["light"]["shadows"][key] = value; + } ); + } + // merge fog settings with global settings + { + const auto& globalSettings = ext::config["engine"]["scenes"]["lights"]["fog"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( serializer["light"]["fog"][key] ) ) return; + serializer["light"]["fog"][key] = value; + } ); + } - /*this->*/shadow.enabled = ext::config["engine"]["scenes"]["shadows"]["enabled"].as(true) && serializer["light"]["shadows"].as(true); - /*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as(); - /*this->*/shadow.max = ext::config["engine"]["scenes"]["shadows"]["max"].as(); - /*this->*/shadow.update = ext::config["engine"]["scenes"]["shadows"]["update"].as(); - /*this->*/shadow.typeMap = ext::config["engine"]["scenes"]["shadows"]["map type"].as(1); + /*this->*/max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as(/*this->*/max.textures2D); + /*this->*/max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as(/*this->*/max.texturesCube); + /*this->*/max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as(/*this->*/max.textures3D); - /*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as(true) && serializer["light"]["should"].as(true); - /*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as(/*this->*/light.max); - /*this->*/light.ambient = uf::vector::decode( serializer["light"]["ambient"], pod::Vector4f{ 1, 1, 1, 1 } ); - /*this->*/light.specular = uf::vector::decode( serializer["light"]["specular"], pod::Vector4f{ 1, 1, 1, 1 } ); - /*this->*/light.exposure = serializer["light"]["exposure"].as(1.0f); - /*this->*/light.gamma = serializer["light"]["gamma"].as(2.2f); - /*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as(ext::config["engine"]["scenes"]["bloom"]["brightnessThreshold"].as(1.0f)); - /*this->*/light.useLightmaps = ext::config["engine"]["scenes"]["lights"]["useLightmaps"].as(true); + /*this->*/shadow.enabled = serializer["light"]["shadows"]["enabled"].as(/*this->*/shadow.enabled); + /*this->*/shadow.samples = serializer["light"]["shadows"]["samples"].as(/*this->*/shadow.samples); + /*this->*/shadow.max = serializer["light"]["shadows"]["max"].as(/*this->*/shadow.max); + /*this->*/shadow.update = serializer["light"]["shadows"]["update"].as(/*this->*/shadow.update); + /*this->*/shadow.typeMap = serializer["light"]["shadows"]["map type"].as(/*this->*/shadow.typeMap); - /*this->*/bloom.scale = serializer["bloom"]["scale"].as(ext::config["engine"]["scenes"]["bloom"]["scale"].as(bloom.scale)); - /*this->*/bloom.strength = serializer["bloom"]["strength"].as(ext::config["engine"]["scenes"]["bloom"]["strength"].as(bloom.strength)); - /*this->*/bloom.sigma = serializer["bloom"]["sigma"].as(ext::config["engine"]["scenes"]["bloom"]["sigma"].as(bloom.sigma)); - /*this->*/bloom.samples = serializer["bloom"]["samples"].as(ext::config["engine"]["scenes"]["bloom"]["samples"].as(bloom.samples)); + /*this->*/light.enabled = serializer["light"]["enabled"].as(/*this->*/light.enabled) && serializer["light"]["should"].as(/*this->*/light.enabled); + /*this->*/light.max = serializer["light"]["max"].as(/*this->*/light.max); + /*this->*/light.ambient = uf::vector::decode( serializer["light"]["ambient"], /*this->*/light.ambient); - /*this->*/fog.color = uf::vector::decode( serializer["light"]["fog"]["color"], pod::Vector3f{ 1, 1, 1 } ); - /*this->*/fog.stepScale = serializer["light"]["fog"]["step scale"].as(); - /*this->*/fog.absorbtion = serializer["light"]["fog"]["absorbtion"].as(); - /*this->*/fog.range = uf::vector::decode( serializer["light"]["fog"]["range"], pod::Vector2f{ 0, 0 } ); - /*this->*/fog.density.offset = uf::vector::decode( serializer["light"]["fog"]["density"]["offset"], pod::Vector4f{ 0, 0, 0, 0 } ); - /*this->*/fog.density.timescale = serializer["light"]["fog"]["density"]["timescale"].as(); - /*this->*/fog.density.threshold = serializer["light"]["fog"]["density"]["threshold"].as(); - /*this->*/fog.density.multiplier = serializer["light"]["fog"]["density"]["multiplier"].as(); - /*this->*/fog.density.scale = serializer["light"]["fog"]["density"]["scale"].as(); + /*this->*/light.exposure = serializer["light"]["exposure"].as(/*this->*/light.exposure); + /*this->*/light.gamma = serializer["light"]["gamma"].as(/*this->*/light.gamma); + /*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as(/*this->*/light.brightnessThreshold); + /*this->*/light.useLightmaps = serializer["light"]["useLightmaps"].as(/*this->*/light.useLightmaps); + + /*this->*/bloom.scale = serializer["light"]["bloom"]["scale"].as(/*this->*/bloom.scale); + /*this->*/bloom.strength = serializer["light"]["bloom"]["strength"].as(/*this->*/bloom.strength); + /*this->*/bloom.sigma = serializer["light"]["bloom"]["sigma"].as(/*this->*/bloom.sigma); + /*this->*/bloom.samples = serializer["light"]["bloom"]["samples"].as(/*this->*/bloom.samples); + + /*this->*/fog.color = uf::vector::decode( serializer["light"]["fog"]["color"], /*this->*/fog.color ); + /*this->*/fog.stepScale = serializer["light"]["fog"]["step scale"].as( /*this->*/fog.stepScale ); + /*this->*/fog.absorbtion = serializer["light"]["fog"]["absorbtion"].as( /*this->*/fog.absorbtion ); + /*this->*/fog.range = uf::vector::decode( serializer["light"]["fog"]["range"], /*this->*/fog.range ); + /*this->*/fog.density.offset = uf::vector::decode( serializer["light"]["fog"]["density"]["offset"], /*this->*/fog.density.offset ); + /*this->*/fog.density.timescale = serializer["light"]["fog"]["density"]["timescale"].as(/*this->*/fog.density.timescale); + /*this->*/fog.density.threshold = serializer["light"]["fog"]["density"]["threshold"].as(/*this->*/fog.density.threshold); + /*this->*/fog.density.multiplier = serializer["light"]["fog"]["density"]["multiplier"].as(/*this->*/fog.density.multiplier); + /*this->*/fog.density.scale = serializer["light"]["fog"]["density"]["scale"].as(/*this->*/fog.density.scale); - /*this->*/sky.box.filename = serializer["sky"]["box"]["filename"].as(sky.box.filename); + /*this->*/sky.box.filename = serializer["sky"]["box"]["filename"].as(/*this->*/sky.box.filename); + + /*this->*/shader.mode = serializer["system"]["renderer"]["shader"]["mode"].as(/*this->*/shader.mode); + /*this->*/shader.scalar = serializer["system"]["renderer"]["shader"]["scalar"].as(/*this->*/shader.scalar); + /*this->*/shader.parameters = uf::vector::decode( serializer["system"]["renderer"]["shader"]["parameters"], /*this->*/shader.parameters ); + /*this->*/shader.frameAccumulateLimit = serializer["system"]["renderer"]["shader"]["frame accumulate limit"].as(/*this->*/shader.frameAccumulateLimit); - /*this->*/shader.mode = serializer["system"]["renderer"]["shader"]["mode"].as(); - /*this->*/shader.scalar = serializer["system"]["renderer"]["shader"]["scalar"].as(); - /*this->*/shader.parameters = uf::vector::decode( serializer["system"]["renderer"]["shader"]["parameters"], pod::Vector4f{0,0,0,0} ); - /*this->*/shader.frameAccumulateLimit = serializer["system"]["renderer"]["shader"]["frame accumulate limit"].as(0); ext::json::forEach( serializer["system"]["renderer"]["shader"]["parameters"], [&]( uint32_t i, const ext::json::Value& value ){ if ( value.as() == "time" ) /*this->*/shader.time = i; }); + if ( 0 <= /*this->*/shader.time && /*this->*/shader.time < 4 ) { /*this->*/shader.parameters[/*this->*/shader.time] = uf::physics::time::current; } diff --git a/ext/behaviors/scene/behavior.h b/ext/behaviors/scene/behavior.h index 34b4cca2..1657eb8c 100644 --- a/ext/behaviors/scene/behavior.h +++ b/ext/behaviors/scene/behavior.h @@ -22,7 +22,7 @@ namespace ext { bool enabled = true; uint32_t max = 256; pod::Vector4f ambient = {0,0,0,1}; - pod::Vector4f specular = {1,1,1,1}; + pod::Vector4f _placeholder = {1,1,1,1}; float exposure = 1.0f; float gamma = 1.0f; float brightnessThreshold = 1.0f; diff --git a/ext/behaviors/soundemitter/behavior.cpp b/ext/behaviors/soundemitter/behavior.cpp index 85038dce..2e8c1f99 100644 --- a/ext/behaviors/soundemitter/behavior.cpp +++ b/ext/behaviors/soundemitter/behavior.cpp @@ -86,7 +86,7 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) { ext::json::Value json = metadata["audio"]; json["filename"] = payload.filename; - this->callHook("sound:Emit.%UID%", json); + this->lazyCallHook("sound:Emit.%UID%", json); }); } void ext::SoundEmitterBehavior::tick( uf::Object& self ) { diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index 7fd191a8..6f32fb0a 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -31,15 +31,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) { auto& sceneMetadataJson = scene.getComponent(); auto& sceneTextures = this->getComponent(); - // merge vxgi settings with global settings - { - const auto& globalSettings = ext::config["engine"]["scenes"]["vxgi"]; - ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ - if ( !ext::json::isNull( metadataJson["vxgi"][key] ) ) return; - metadataJson["vxgi"][key] = value; - } ); - } - UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson); // initialize voxel map @@ -465,26 +456,35 @@ void ext::VoxelizerSceneBehavior::Metadata::serialize( uf::Object& self, uf::Ser serializer["vxgi"]["extents"]["max"] = uf::vector::encode(/*this->*/extents.max); } void ext::VoxelizerSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) { - /*this->*/voxelSize.x = serializer["vxgi"]["size"].as(96); - /*this->*/voxelSize.y = serializer["vxgi"]["size"].as(96); - /*this->*/voxelSize.z = serializer["vxgi"]["size"].as(96); + // merge vxgi settings with global settings + { + const auto& globalSettings = ext::config["engine"]["scenes"]["vxgi"]; + ext::json::forEach( globalSettings, [&]( const uf::stl::string& key, const ext::json::Value& value ){ + if ( !ext::json::isNull( serializer["vxgi"][key] ) ) return; + serializer["vxgi"][key] = value; + } ); + } + + /*this->*/voxelSize.x = serializer["vxgi"]["size"].as(/*this->*/voxelSize.x); + /*this->*/voxelSize.y = serializer["vxgi"]["size"].as(/*this->*/voxelSize.y); + /*this->*/voxelSize.z = serializer["vxgi"]["size"].as(/*this->*/voxelSize.z); - /*this->*/limiter.frequency = serializer["vxgi"]["limiter"].as(1); + /*this->*/limiter.frequency = serializer["vxgi"]["limiter"].as(/*this->*/limiter.frequency); - /*this->*/dispatchSize.x = serializer["vxgi"]["dispatch"].as(8); - /*this->*/dispatchSize.y = serializer["vxgi"]["dispatch"].as(8); - /*this->*/dispatchSize.z = serializer["vxgi"]["dispatch"].as(8); + /*this->*/dispatchSize.x = serializer["vxgi"]["dispatch"].as(/*this->*/dispatchSize.x); + /*this->*/dispatchSize.y = serializer["vxgi"]["dispatch"].as(/*this->*/dispatchSize.x); + /*this->*/dispatchSize.z = serializer["vxgi"]["dispatch"].as(/*this->*/dispatchSize.x); - /*this->*/cascades = serializer["vxgi"]["cascades"].as(4); - /*this->*/cascadePower = serializer["vxgi"]["cascadePower"].as(4); - /*this->*/granularity = serializer["vxgi"]["granularity"].as(4); - /*this->*/voxelizeScale = serializer["vxgi"]["voxelizeScale"].as(1); - /*this->*/occlusionFalloff = serializer["vxgi"]["occlusionFalloff"].as(128); - /*this->*/traceStartOffsetFactor = serializer["vxgi"]["traceStartOffsetFactor"].as(1.0f); - /*this->*/shadows = serializer["vxgi"]["shadows"].as(0); + /*this->*/cascades = serializer["vxgi"]["cascades"].as(/*this->*/cascades); + /*this->*/cascadePower = serializer["vxgi"]["cascadePower"].as(/*this->*/cascadePower); + /*this->*/granularity = serializer["vxgi"]["granularity"].as(/*this->*/granularity); + /*this->*/voxelizeScale = serializer["vxgi"]["voxelizeScale"].as(/*this->*/voxelizeScale); + /*this->*/occlusionFalloff = serializer["vxgi"]["occlusionFalloff"].as(/*this->*/occlusionFalloff); + /*this->*/traceStartOffsetFactor = serializer["vxgi"]["traceStartOffsetFactor"].as(/*this->*/traceStartOffsetFactor); + /*this->*/shadows = serializer["vxgi"]["shadows"].as(/*this->*/shadows); - /*this->*/extents.min = uf::vector::decode( serializer["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} ); - /*this->*/extents.max = uf::vector::decode( serializer["vxgi"]["extents"]["max"], pod::Vector3f{ 32, 32, 32} ); + /*this->*/extents.min = uf::vector::decode( serializer["vxgi"]["extents"]["min"], /*this->*/extents.min ); + /*this->*/extents.max = uf::vector::decode( serializer["vxgi"]["extents"]["max"], /*this->*/extents.max ); } #undef this #endif \ No newline at end of file diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 0fb24bdd..76fca3f5 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -1019,21 +1019,26 @@ void ext::GuiBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer["gui"][key] = serializer["text settings"][key]; } - color = uf::vector::decode( serializer["gui"]["color"], color ); - world = serializer["gui"]["world"].as(); + /*this->*/color = uf::vector::decode( serializer["gui"]["color"], /*this->*/color ); + /*this->*/world = serializer["gui"]["world"].as(/*this->*/world); + if ( serializer["gui"]["only model"].as() ) mode = 1; else if ( serializer["gui"]["world"].as() ) mode = 2; else if ( serializer["gui"]["projection"].as() ) mode = 3; - box.min = uf::vector::decode( serializer["box"]["min"], box.min ); - box.max = uf::vector::decode( serializer["box"]["max"], box.max ); - clickable = serializer["gui"]["clickable"].as(); - clicked = serializer["gui"]["clicked"].as(); - hoverable = serializer["gui"]["hoverable"].as(); - hovered = serializer["gui"]["hovered"].as(); - uv = uf::vector::decode( serializer["gui"]["uv"], uv ); - shader = serializer["gui"]["shader"].as(); - depth = serializer["gui"]["depth"].as(); - alpha = serializer["gui"]["alpha"].as(); + + /*this->*/box.min = uf::vector::decode( serializer["box"]["min"], /*this->*/box.min ); + /*this->*/box.max = uf::vector::decode( serializer["box"]["max"], /*this->*/box.max ); + + /*this->*/clickable = serializer["gui"]["clickable"].as(/*this->*/clickable); + /*this->*/clicked = serializer["gui"]["clicked"].as(/*this->*/clicked); + /*this->*/hoverable = serializer["gui"]["hoverable"].as(/*this->*/hoverable); + /*this->*/hovered = serializer["gui"]["hovered"].as(/*this->*/hovered); + /*this->*/uv = uf::vector::decode( serializer["gui"]["uv"], /*this->*/uv ); + + /*this->*/shader = serializer["gui"]["shader"].as(/*this->*/shader); + /*this->*/depth = serializer["gui"]["depth"].as(/*this->*/depth); + /*this->*/alpha = serializer["gui"]["alpha"].as(/*this->*/alpha); + if ( serializer["gui"]["alpha"].is() ) color[3] *= alpha; } @@ -1066,24 +1071,24 @@ void ext::GuiBehavior::GlyphMetadata::deserialize( uf::Object& self, uf::Seriali if ( !ext::json::isNull( serializer[key] ) ) serializer["gui"][key] = serializer[key]; if ( !ext::json::isNull( serializer["text settings"][key] ) ) serializer["gui"][key] = serializer["text settings"][key]; } - /*this->*/font = serializer["gui"]["font"].as(); - /*this->*/string = serializer["gui"]["string"].as(); + /*this->*/font = serializer["gui"]["font"].as(/*this->*/font); + /*this->*/string = serializer["gui"]["string"].as(/*this->*/string); - /*this->*/scale = serializer["gui"]["scale"].as(); + /*this->*/scale = serializer["gui"]["scale"].as(/*this->*/scale); /*this->*/padding = uf::vector::decode( serializer["gui"]["padding"], /*this->*/padding ); - /*this->*/spread = serializer["gui"]["spread"].as(); - /*this->*/size = serializer["gui"]["size"].as(); - /*this->*/weight = serializer["gui"]["weight"].as(); + /*this->*/spread = serializer["gui"]["spread"].as(/*this->*/spread); + /*this->*/size = serializer["gui"]["size"].as(/*this->*/size); + /*this->*/weight = serializer["gui"]["weight"].as(/*this->*/weight); #if UF_USE_OPENGL /*this->*/sdf = false; #else - /*this->*/sdf = serializer["gui"]["sdf"].as(); + /*this->*/sdf = serializer["gui"]["sdf"].as(/*this->*/sdf); #endif - /*this->*/shadowbox = serializer["gui"]["shadowbox"].as(); + /*this->*/shadowbox = serializer["gui"]["shadowbox"].as(/*this->*/shadowbox); /*this->*/stroke = uf::vector::decode( serializer["gui"]["stroke"], /*this->*/stroke ); - /*this->*/origin = serializer["gui"]["origin"].as(); - /*this->*/align = serializer["gui"]["align"].as(); - /*this->*/direction = serializer["gui"]["direction"].as(); + /*this->*/origin = serializer["gui"]["origin"].as(/*this->*/origin); + /*this->*/align = serializer["gui"]["align"].as(/*this->*/align); + /*this->*/direction = serializer["gui"]["direction"].as(/*this->*/direction); } #undef this \ No newline at end of file diff --git a/ext/main.cpp b/ext/main.cpp index 30e92e8a..ba6a96eb 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -240,6 +240,8 @@ void EXT_API ext::initialize() { uf::userdata::autoDestruct = ::json["engine"]["debug"]["userdata"]["auto destruct"].as( uf::userdata::autoDestruct ); uf::userdata::autoValidate = ::json["engine"]["debug"]["userdata"]["auto validate"].as( uf::userdata::autoValidate ); + + uf::Object::deferLazyCalls = ::json["engine"]["debug"]["hooks"]["defer lazy calls"].as( uf::Object::deferLazyCalls ); } { @@ -436,7 +438,7 @@ void EXT_API ext::initialize() { if ( uf::renderer::settings::pipelines::rt ) { uf::renderer::settings::pipelines::vxgi = false; uf::renderer::settings::pipelines::culling = false; - ::json["engine"]["scenes"]["shadows"]["enabled"] = false; + ::json["engine"]["scenes"]["lights"]["shadows"]["enabled"] = false; } #define JSON_TO_VKFORMAT( key ) if ( configRenderJson["formats"][#key].is() ) {\