From 60e64ccb0dff17d7c672cffceb005e719563df5a Mon Sep 17 00:00:00 2001 From: mrq Date: Sat, 16 Jul 2022 23:28:00 -0500 Subject: [PATCH] Commit for 2022.07.16 23-28-12.7z --- bin/data/config.json | 12 +- bin/data/entities/door.json | 3 + bin/data/entities/light.json | 15 +- bin/data/entities/model.json | 6 +- bin/data/entities/player.json | 7 +- bin/data/entities/playerLight.json | 4 +- bin/data/entities/prop.json | 3 + bin/data/entities/scripts/door.lua | 10 +- bin/data/scenes/construct/gm_construct.json | 56 ++- bin/data/scenes/construct/player.json | 5 +- bin/data/scenes/construct/scene.json | 4 +- bin/data/scenes/construct/sound.json | 34 ++ .../scenes/sh2_mcdonalds/sh2_mcdonalds.json | 10 +- bin/data/scenes/ss2/medsci.json | 11 +- bin/data/shaders/display/subpass.h | 10 - client/client/ext.cpp | 2 +- engine/inc/uf/engine/graph/graph.h | 1 + engine/inc/uf/engine/object/object.h | 2 + engine/inc/uf/engine/object/object.inl | 6 +- engine/inc/uf/ext/json/nlohmann.h | 20 +- engine/inc/uf/ext/vulkan/rendermode.h | 2 + engine/inc/uf/ext/vulkan/rendermodes/base.h | 1 + engine/inc/uf/ext/vulkan/vulkan.h | 2 + engine/inc/uf/macros.h | 19 +- engine/inc/uf/utils/math/physics.h | 9 +- engine/inc/uf/utils/time/time.h | 8 + engine/src/engine/asset/asset.cpp | 2 +- engine/src/engine/entity/entity.cpp | 2 +- engine/src/engine/graph/decode.cpp | 23 +- engine/src/engine/graph/encode.cpp | 2 +- engine/src/engine/graph/graph.cpp | 174 +++++++--- engine/src/engine/object/behavior.cpp | 11 +- engine/src/engine/object/object.cpp | 18 +- engine/src/engine/scene/behavior.cpp | 15 + engine/src/engine/scene/scene.cpp | 7 + engine/src/ext/bullet/bullet.cpp | 2 +- engine/src/ext/gltf/processPrimitives.inl | 2 +- engine/src/ext/reactphysics/reactphysics.cpp | 2 +- engine/src/ext/vulkan/device.cpp | 2 +- engine/src/ext/vulkan/graphic.cpp | 20 +- engine/src/ext/vulkan/rendermode.cpp | 76 ++++- engine/src/ext/vulkan/rendermodes/base.cpp | 242 ++++++++++--- engine/src/ext/vulkan/rendermodes/compute.cpp | 3 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 322 +++++++++++++----- .../ext/vulkan/rendermodes/rendertarget.cpp | 111 ++---- engine/src/ext/vulkan/shader.cpp | 2 + engine/src/ext/vulkan/vulkan.cpp | 5 +- engine/src/ext/xatlas/xatlas.cpp | 155 ++++++--- engine/src/utils/math/physics.cpp | 2 + engine/src/utils/serialize/serializer.cpp | 4 +- engine/src/utils/time/time.cpp | 8 +- ext/behaviors/baking/behavior.cpp | 6 +- ext/behaviors/light/behavior.cpp | 5 + ext/behaviors/light/behavior.h | 1 + ext/behaviors/player/behavior.cpp | 11 +- ext/behaviors/raytrace/behavior.cpp | 7 +- ext/behaviors/scene/behavior.cpp | 16 +- ext/behaviors/scene/behavior.h | 4 +- ext/behaviors/voxelizer/behavior.cpp | 2 +- ext/gui/manager/behavior.cpp | 4 +- ext/main.cpp | 55 +-- 61 files changed, 1102 insertions(+), 483 deletions(-) create mode 100644 bin/data/scenes/construct/sound.json diff --git a/bin/data/config.json b/bin/data/config.json index 7ffa230c..4b591c30 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -2,8 +2,8 @@ "engine": { "scenes": { "start": "SH2_McDonalds", - "meshes": { "interleaved": false }, "matrix": { "reverseInfinite": true }, + "meshes": { "interleaved": false }, "lights": { "enabled": true, "useLightmaps": false, "max": 48 @@ -54,10 +54,15 @@ "threshold": 1.0 } }, + "graph": { + "initial buffer elements": 131072 + }, "ext": { "vulkan": { "validation": { "enabled": false, "filters": [ + "MessageID = 0x35d7ea98", // VUID-vkUpdateDescriptorSets-None-03047 () + "MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps) "MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls) "MessageID = 0x23e43bb7", // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls) @@ -98,9 +103,10 @@ "defaultStageBuffers": true }, "pipelines": { + "deferred": true, "vsync": false, "hdr": false, - "vxgi": false, + "vxgi": true, "culling": true, "bloom": false, "rt": false @@ -200,7 +206,7 @@ "compression": "gz" }, "imgui": { - "enabled": true + "enabled": false }, "reactphysics": { "timescale": 0.01666666666, diff --git a/bin/data/entities/door.json b/bin/data/entities/door.json index 8ba9c58c..66d00173 100644 --- a/bin/data/entities/door.json +++ b/bin/data/entities/door.json @@ -1,5 +1,8 @@ { "assets": ["./scripts/door.lua"], + "behaviors": [ + "SoundEmitterBehavior" + ], "metadata": { "physics": { "mass": 0, diff --git a/bin/data/entities/light.json b/bin/data/entities/light.json index aa6ed7cb..061654ef 100644 --- a/bin/data/entities/light.json +++ b/bin/data/entities/light.json @@ -13,15 +13,8 @@ // "mode": "once" "mode": "in-range" }, - "behavior-0": { - "tick": { - "head loop children": true, - "forward iteration": false, - "multithreading": false - }, - "render": { - "multithreading": false - } + "hot reload": { + "enabled": true } }, "metadata": { @@ -35,8 +28,8 @@ "slope": 1.75, "shader": 0.000005 //0.000000005 }, - "radius": [0.001, 256.0], - "resolution": 1024, + "radius": [0.1, 0], + "resolution": 512, "shadows": true, "static": false } diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index 438f0083..125fba46 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -33,7 +33,7 @@ "precision": 4, "combined": false, "encode buffers": true, - "unwrap": true, // "tagged", + "unwrap": "tagged", "quit": true }, "baking": { @@ -46,13 +46,13 @@ "output": "./lightmap.%i.png", "settings": { "useInputMeshUvs": true, - "maxIterations": 4, + "maxIterations": 1, // "maxChartSize": 0, "padding": 4, // "texelsPerUnit": 0, "bilinear": true, "blockAlign": true, - "bruteForce": true, + "bruteForce": false, "rotateChartsToAxis": false, "rotateCharts": true diff --git a/bin/data/entities/player.json b/bin/data/entities/player.json index 8513c136..da3a0065 100644 --- a/bin/data/entities/player.json +++ b/bin/data/entities/player.json @@ -6,6 +6,7 @@ "SoundEmitterBehavior" ], "ignore": false, +/* "transform": { "position": [ 0, 0, 0 ], "rotation": { @@ -14,6 +15,7 @@ }, "scale": [ 1, 1, 1 ] }, +*/ "assets": [ // { "filename": "./playerModel.json", "delay": 1 }, "./playerModel.json", @@ -64,7 +66,8 @@ "look": 1, "floored": { "feet": [ 0, -1.5, 0 ], - "floor": [ 0, -0.5, 0 ], + // "floor": [ 0, -0.5, 0 ], + "floor": [ 0, -1.0, 0 ], "print": false } }, @@ -96,7 +99,7 @@ "current":[ null, 0, null ] }, "settings": { - "fov" : 90, + "fov" : 90.0, "clip" : [ 0.1, 64.0 ], "size" : [ 0, 0 ] } diff --git a/bin/data/entities/playerLight.json b/bin/data/entities/playerLight.json index ecbce57b..ad807d00 100644 --- a/bin/data/entities/playerLight.json +++ b/bin/data/entities/playerLight.json @@ -14,7 +14,7 @@ }, "metadata": { "light": { - "type": "point", + "type": "spot", "color": [1, 1, 1], "power": 30, "fov": 90, @@ -24,7 +24,7 @@ "shader": 0.000005 //0.000000005 }, "radius": [0.001, 0], - "resolution": 1024, + "resolution": 512, "shadows": false, "static": false } diff --git a/bin/data/entities/prop.json b/bin/data/entities/prop.json index e5aa02b4..f8dbb274 100644 --- a/bin/data/entities/prop.json +++ b/bin/data/entities/prop.json @@ -1,5 +1,8 @@ { "assets": [], + "behaviors": [ + "SoundEmitterBehavior" + ], "metadata": { "holdable": true, "physics": { diff --git a/bin/data/entities/scripts/door.lua b/bin/data/entities/scripts/door.lua index 7a34240b..8550a7fc 100644 --- a/bin/data/entities/scripts/door.lua +++ b/bin/data/entities/scripts/door.lua @@ -22,11 +22,10 @@ if metadata["normal"] ~= nil then end local starting = Quaternion(transform.orientation) local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] )) -local soundEmitter = ent:loadChild("./sound.json",true) local playSound = function( key, loop ) if not loop then loop = false end local url = "/door/" .. key .. ".ogg" - soundEmitter:queueHook("sound:Emit.%UID%", { + ent:queueHook("sound:Emit.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]), spatial = true, streamed = true, @@ -36,13 +35,13 @@ local playSound = function( key, loop ) end local stopSound = function( key ) local url = "/door/" .. key .. ".ogg" - soundEmitter:queueHook("sound:Stop.%UID%", { + ent:queueHook("sound:Stop.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]) }, 0) end local playSoundscape = function( key ) local url = "/soundscape/" .. key .. ".ogg" - soundEmitter:queueHook("sound:Emit.%UID%", { + ent:queueHook("sound:Emit.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]), spatial = false, volume = "sfx", @@ -52,11 +51,10 @@ local playSoundscape = function( key ) end local stopSoundscape = function( key ) local url = "/soundscape/" .. key .. ".ogg" - soundEmitter:queueHook("sound:Stop.%UID%", { + ent:queueHook("sound:Stop.%UID%", { filename = string.resolveURI(url, metadata["system"]["root"]) }, 0) end -soundEmitter:getComponent("Transform"):setReference( transform ) -- on tick ent:bind( "tick", function(self) -- transform.orientation = starting:slerp( ending, math.cos(time.current() * speed) * 0.5 + 0.5 ) diff --git a/bin/data/scenes/construct/gm_construct.json b/bin/data/scenes/construct/gm_construct.json index aee8ef86..2dc1fbec 100644 --- a/bin/data/scenes/construct/gm_construct.json +++ b/bin/data/scenes/construct/gm_construct.json @@ -3,27 +3,57 @@ "assets": [ // { "filename": "./models/gm_construct.glb" } { "filename": "./models/gm_construct/graph.json" } + + // { "filename": "./models/rp_downtown_v2.glb" } + // { "filename": "./models/rp_downtown_v2/graph.json" } ], "metadata": { "model": { "baking": { - "enabled": true, - "resolution": 2048, - "settings": { - "useInputMeshUvs": false - } + "enabled": false + }, + "renderer": { + "separate": true }, "tags": { - "/^worldspawn/": { + "/^worldspawn$/": { "physics": { "type": "mesh", "static": true }, - "grid": { "size": [5,2,5], "epsilon": 1.0, "cleanup": true, "print": true } + // "grid": { "size": [2,1,2], "epsilon": 1.0, "cleanup": true, "print": true }, + // "unwrap mesh": true, + "optimize mesh": { "simplify": 0 } }, - "info_player_spawn": { - "action": "attach", - "filename": "./player.json", - "preserve orientation": true - } + "/^worldspawn_skybox$/": { "ignore": true }, + "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, + "global": true, + "bias": { + "constant": 1.25, + "slope": 1.75, + "shader": 0.0000025 + }, + "radius": [0.95, 0], + "resolution": 1536 + } }, + + // "/^light_[^e]/": { "ignore": true }, + // "/^func/": { "ignore": true }, + // "/^prop/": { "ignore": 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 ] } } }*/ }, + "/^prop_dynamic/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ }, + + "/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } }, + "/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } }, + + "/^gm_construct\\/water/": { "material": { + "base": [ 0.027, 0.227, 0.259, 0.5 ], + "fRoughness": 0.3 + } } } - } + } } } \ No newline at end of file diff --git a/bin/data/scenes/construct/player.json b/bin/data/scenes/construct/player.json index 38f04797..bd6ad5ef 100644 --- a/bin/data/scenes/construct/player.json +++ b/bin/data/scenes/construct/player.json @@ -2,7 +2,6 @@ "import": "/player.json", "assets": [ // { "filename": "/gui/hud/hud.json", "delay": 0 } - ], - "metadata": { - } + ] +// "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } } \ No newline at end of file diff --git a/bin/data/scenes/construct/scene.json b/bin/data/scenes/construct/scene.json index fc0e9f8b..aaf567df 100644 --- a/bin/data/scenes/construct/scene.json +++ b/bin/data/scenes/construct/scene.json @@ -28,7 +28,9 @@ "exposure": 1.0, "gamma": 1.0, - "ambient": [ 0.15, 0.15, 0.15 ], + // "ambient": [ 0.15, 0.15, 0.15 ], + "ambient": [ 0.5, 0.5, 0.5 ], + // "ambient": [ 0.8, 0.8, 0.8 ], "fog-disabled": { "color": [ 0.5, 0.5, 0.5 ], diff --git a/bin/data/scenes/construct/sound.json b/bin/data/scenes/construct/sound.json new file mode 100644 index 00000000..351f92fe --- /dev/null +++ b/bin/data/scenes/construct/sound.json @@ -0,0 +1,34 @@ +{ + "type": "Object", + "name": "Sound Emitter", + "ignore": false, + "assets": [ + ], + "behaviors": [ + "SoundEmitterBehavior" + ], + "transform": { + "reference": true + }, + "system": { + "hot reload": { + "enabled": true + }, + "defaults": { + "render": true, + "asset load": true + }, + "load": { + "ignore": true + } + }, + "metadata": { + "audio": { + "spatial": true, + "loop": false, + "volume": 1, + "rolloffFactor": 0.5, + "epsilon": 0.5 + } + } +} \ No newline at end of file diff --git a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json index 8d4cfac0..8a147f2b 100644 --- a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json +++ b/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json @@ -39,7 +39,7 @@ "grid": { "size": [6,1,6], "epsilon": 1.0, "cleanup": true, "print": true } }, "info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true }, - + "func_door_rotating_5409": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_door_rotating_5487": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } }, "func_door_rotating_5495": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle": 1.570795, "normal": [ 1,0,0] } } }, @@ -52,14 +52,14 @@ "func_physbox_5212": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_physbox_5548": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_physbox_5931": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, + + "/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } }, + "/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } }, + "/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_door_rotating_5568": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_door_rotating_5576": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "func_door_rotating_5584": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, - "/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, - - "/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } }, - "/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } }, "tools/toolsnodraw": { "material": { "base": [0, 0, 0, 0] } }, "materials/models/props_wasteland/prison_lamp001a": { "material": { "emissive": [0, 0, 0, 0] } }, diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index 8a087076..2e774461 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -41,18 +41,19 @@ "light_30145": { "light": { "power": 120 } }, - "prop_camera_103001_light": { /*"bake": false,*/ "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, - "prop_camera_103118_light": { /*"bake": false,*/ "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, - "prop_camera_103001": { /*"bake": false,*/ "action": "load", "payload": { "import": "./camera.json" } }, - "prop_camera_103118": { /*"bake": false,*/ "action": "load", "payload": { "import": "./camera.json" } }, + "/^prop_camera_.+?_light/": { /*"bake": false,*/ "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, + "/prop_camera_/": { /*"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 ] } } }, "func_movelinear_103114": { /*"bake": false,*/ "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,-3.0,0 ] } } }, "/^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 ] } } } }, "/^func_physbox/": { "action": "load", "payload": { "import": "/prop.json" } }, - "/^prop_physics/": { "action": "load", "payload": { "import": "/prop.json" } } + "/^prop_/": { "action": "load", "payload": { "import": "/prop.json" } } } } } diff --git a/bin/data/shaders/display/subpass.h b/bin/data/shaders/display/subpass.h index d876bbf2..8704ee5f 100644 --- a/bin/data/shaders/display/subpass.h +++ b/bin/data/shaders/display/subpass.h @@ -9,10 +9,6 @@ #define MAX_TEXTURES TEXTURES //#define TEXTURE_WORKAROUND 0 -#define BUFFER_REFERENCE 1 -#define UINT64_ENABLED 1 - - #include "../common/macros.h" layout (constant_id = 0) const uint TEXTURES = 512; @@ -205,12 +201,6 @@ void populateSurface() { const Instance instance = instances[instanceID]; surface.instance = instance; - { - const InstanceAddresses instanceAddresses = instanceAddresses[instanceID]; - // uint64_t address = (instanceAddresses.vertex[0] << 32) & instanceAddresses.vertex[1]; - Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex)); - } - const Material material = materials[surface.instance.materialID]; surface.material.albedo = material.colorBase; surface.material.metallic = material.factorMetallic; diff --git a/client/client/ext.cpp b/client/client/ext.cpp index 3cecf74c..1fcd15e6 100644 --- a/client/client/ext.cpp +++ b/client/client/ext.cpp @@ -128,7 +128,7 @@ void client::tick() { if ( client::window.hasFocus() ) { // fullscreener - TIMER(1, (uf::inputs::kbm::states::LAlt || uf::inputs::kbm::states::RAlt) && uf::inputs::kbm::states::Enter && ) { + TIMER(1, (uf::inputs::kbm::states::LAlt || uf::inputs::kbm::states::RAlt) && uf::inputs::kbm::states::Enter ) { uf::renderer::states::resized = true; client::window.toggleFullscreen( false ); } diff --git a/engine/inc/uf/engine/graph/graph.h b/engine/inc/uf/engine/graph/graph.h index 87e89f4c..98cab243 100644 --- a/engine/inc/uf/engine/graph/graph.h +++ b/engine/inc/uf/engine/graph/graph.h @@ -100,6 +100,7 @@ namespace pod { namespace uf { namespace graph { + extern UF_API size_t initialBufferElements; extern UF_API pod::Graph::Storage storage; } } diff --git a/engine/inc/uf/engine/object/object.h b/engine/inc/uf/engine/object/object.h index 3ce43ec3..2372d95a 100644 --- a/engine/inc/uf/engine/object/object.h +++ b/engine/inc/uf/engine/object/object.h @@ -44,7 +44,9 @@ namespace uf { template uf::Hooks::return_t callHook( const uf::stl::string& name, const T& payload ); void queueHook( const uf::stl::string&, float = 0 ); + void queueHook( const uf::stl::string&, double ); void queueHook( const uf::stl::string&, const ext::json::Value& json, float = 0 ); + void queueHook( const uf::stl::string&, const ext::json::Value& json, double ); template void queueHook( const uf::stl::string&, const T&, float = 0 ); diff --git a/engine/inc/uf/engine/object/object.inl b/engine/inc/uf/engine/object/object.inl index 15186695..d94a4bac 100644 --- a/engine/inc/uf/engine/object/object.inl +++ b/engine/inc/uf/engine/object/object.inl @@ -36,13 +36,13 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const T& template void uf::Object::queueHook( const uf::stl::string& name, const T& p, float d ) { - if ( !uf::Object::timer.running() ) uf::Object::timer.start(); - double start = uf::Object::timer.elapsed().asDouble(); +// if ( !uf::Object::timer.running() ) uf::Object::timer.start(); +// double start = uf::Object::timer.elapsed().asDouble(); auto& metadata = this->getComponent(); auto& queue = metadata.hooks.queue.emplace_back(uf::ObjectBehavior::Metadata::Queued{ .name = name, - .timeout = start + d, + .timeout = uf::time::current + d, .type = 1, }); queue.userdata.create(p); diff --git a/engine/inc/uf/ext/json/nlohmann.h b/engine/inc/uf/ext/json/nlohmann.h index a7be28f3..ff0d2614 100644 --- a/engine/inc/uf/ext/json/nlohmann.h +++ b/engine/inc/uf/ext/json/nlohmann.h @@ -13,7 +13,7 @@ #include #include -#define UF_JSON_NLOHMANN_ORDERED 0 +#define UF_JSON_NLOHMANN_ORDERED 1 #define UF_JSON_NLOHMANN_FIFO_MAP 0 namespace uf { @@ -25,13 +25,13 @@ namespace ext { class UF_API Value; #if UF_JSON_NLOHMANN_ORDERED - #if UF_JSON_NLOHMANN_FIFO_MAP - template - using fifo_map = nlohmann::fifo_map, A>; - typedef nlohmann::basic_json base_value; - #else - typedef nlohmann::ordered_json base_value; - #endif + #if UF_JSON_NLOHMANN_FIFO_MAP + template + using fifo_map = nlohmann::fifo_map, A>; + typedef nlohmann::basic_json base_value; + #else + typedef nlohmann::ordered_json base_value; + #endif #else typedef nlohmann::json base_value; #endif @@ -133,14 +133,14 @@ template<> inline bool ext::json::Value::is(bool strict) const template<> inline bool ext::json::Value::is(bool strict) const { return strict ? is_number_unsigned() : is_number(); } #endif template inline T ext::json::Value::as() const { - return !is() ? T() : get(); + return !is(false) ? T() : get(); /* if ( !is() ) return T(); return get(); */ } template inline T ext::json::Value::as( const T& fallback ) const { - return !is() ? fallback : get(); + return !is(false) ? fallback : get(); /* if ( !is() ) return fallback; return get(); diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index c1ddaeb0..c6f6063a 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -66,6 +66,8 @@ namespace ext { bool tryMutex( std::thread::id = std::this_thread::get_id() ); void unlockMutex( std::thread::id = std::this_thread::get_id() ); std::lock_guard guardMutex( std::thread::id = std::this_thread::get_id() ); + + void cleanupAllCommands(); void cleanupCommands( std::thread::id = std::this_thread::get_id() ); virtual ~RenderMode(); diff --git a/engine/inc/uf/ext/vulkan/rendermodes/base.h b/engine/inc/uf/ext/vulkan/rendermodes/base.h index 2d60e1f7..108d6408 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/base.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/base.h @@ -12,6 +12,7 @@ namespace ext { virtual void initialize( Device& device ); virtual void createCommandBuffers( const uf::stl::vector& graphics ); + virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 ); virtual void tick(); virtual void render(); virtual void destroy(); diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 141b66dc..f37ce7ca 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -86,6 +86,7 @@ namespace ext { } namespace pipelines { + extern UF_API bool deferred; extern UF_API bool vsync; extern UF_API bool hdr; extern UF_API bool vxgi; @@ -94,6 +95,7 @@ namespace ext { extern UF_API bool rt; namespace names { + extern UF_API uf::stl::string deferred; extern UF_API uf::stl::string vsync; extern UF_API uf::stl::string hdr; extern UF_API uf::stl::string vxgi; diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index da0b998b..327df7b6 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -3,21 +3,12 @@ #define UF_NS_GET_LAST(name) uf::string::replace( uf::string::split( #name, "::" ).back(), "<>", "" ) -#define TIMER_LAMBDA(x) []() {\ - static uf::Timer timer(false);\ - if ( !timer.running() ) timer.start(uf::Time(-1000000));\ - double time = timer.elapsed();\ - if ( time >= every ) timer.reset();\ - static bool first = true; if ( first ) { first = false; return every; }\ - return time;\ -}; - #define TIMER(x, ...)\ static uf::Timer timer(false);\ if ( !timer.running() ) timer.start(uf::Time(-1000000));\ + struct { bool should = true; } timerState = { __VA_ARGS__ };\ double time = timer.elapsed();\ - if ( time >= x ) timer.reset();\ - if ( __VA_ARGS__ time >= x ) + if ( time >= x && timerState.should && (timer.reset(), true) ) #define UF_DEBUG 1 #if UF_DEBUG @@ -62,12 +53,12 @@ #define UF_TIMER_TRACE(...) {\ auto elapsed = TIMER_TRACE.elapsed().asMicroseconds();\ - if ( elapsed > 0 ) UF_MSG_DEBUG("{} us\t{}", TIMER_TRACE.elapsed().asMicroseconds(), __VA_ARGS__);\ + if ( elapsed > 0 ) UF_MSG_DEBUG("{} us\t{}", TIMER_TRACE.elapsed().asMicroseconds(), ::fmt::format(__VA_ARGS__));\ } #define UF_TIMER_TRACE_RESET(...) {\ auto elapsed = TIMER_TRACE.elapsed().asMicroseconds();\ - if ( elapsed > 0 ) UF_MSG_DEBUG("{} us\t{}", TIMER_TRACE.elapsed().asMicroseconds(), __VA_ARGS__);\ + if ( elapsed > 0 ) UF_MSG_DEBUG("{} us\t{}", TIMER_TRACE.elapsed().asMicroseconds(), ::fmt::format(__VA_ARGS__));\ TIMER_TRACE.reset();\ } @@ -78,7 +69,7 @@ #define UF_TIMER_MULTITRACE(...) {\ TIMER_TRACE_CUR = TIMER_TRACE.elapsed().asMicroseconds();\ - UF_MSG_DEBUG("{} us\t{} us\t{}", TIMER_TRACE_CUR, (TIMER_TRACE_CUR - TIMER_TRACE_PREV), __VA_ARGS__);\ + UF_MSG_DEBUG("{} us\t{} us\t{}", TIMER_TRACE_CUR, (TIMER_TRACE_CUR - TIMER_TRACE_PREV), ::fmt::format(__VA_ARGS__));\ TIMER_TRACE_PREV = TIMER_TRACE_CUR;\ } diff --git a/engine/inc/uf/utils/math/physics.h b/engine/inc/uf/utils/math/physics.h index 6ab2f88d..071f673e 100644 --- a/engine/inc/uf/utils/math/physics.h +++ b/engine/inc/uf/utils/math/physics.h @@ -19,13 +19,8 @@ namespace uf { #endif typedef pod::Math::num_t num_t; - namespace time { - extern UF_API uf::Timer<> timer; - extern UF_API double current; - extern UF_API double previous; - extern UF_API float delta; - extern UF_API float clamp; - } + namespace time = uf::time; + void UF_API initialize(); void UF_API tick(); void UF_API terminate(); diff --git a/engine/inc/uf/utils/time/time.h b/engine/inc/uf/utils/time/time.h index 8e33047d..3deadd96 100644 --- a/engine/inc/uf/utils/time/time.h +++ b/engine/inc/uf/utils/time/time.h @@ -81,6 +81,14 @@ namespace uf { const uf::Time& getStarting() const; const uf::Time& getEnding() const; }; + + namespace time { + extern UF_API uf::Timer<> timer; + extern UF_API double current; + extern UF_API double previous; + extern UF_API float delta; + extern UF_API float clamp; + } } #include "time.inl" diff --git a/engine/src/engine/asset/asset.cpp b/engine/src/engine/asset/asset.cpp index 8d89f2b5..9dcc4bad 100644 --- a/engine/src/engine/asset/asset.cpp +++ b/engine/src/engine/asset/asset.cpp @@ -64,7 +64,7 @@ void uf::Asset::processQueue() { auto jobs = std::move(this->getComponent()); mutex.unlock(); - for ( auto& job : jobs ) tasks.queue([=]{ + for ( auto& job : jobs ) tasks.queue([=, this]{ // C++20 retardation uf::stl::string callback = job.callback; uf::stl::string type = job.type; uf::Asset::Payload payload = job.payload; diff --git a/engine/src/engine/entity/entity.cpp b/engine/src/engine/entity/entity.cpp index f909ccf1..32a92286 100644 --- a/engine/src/engine/entity/entity.cpp +++ b/engine/src/engine/entity/entity.cpp @@ -14,7 +14,7 @@ uf::Entity::~Entity(){ } bool uf::Entity::isValid() const { if ( uf::Entity::memoryPool.size() > 0 && !uf::Entity::memoryPool.exists((void*) this) ) return false; - return this != NULL && (0 < this->m_uid && this->m_uid <= uf::Entity::uids); + return /*this != NULL &&*/ (0 < this->m_uid && this->m_uid <= uf::Entity::uids); } void uf::Entity::setUid() { uf::scene::invalidateGraphs(); diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index dde94ce9..266bc6f3 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -12,7 +12,17 @@ #if UF_ENV_DREAMCAST #define UF_GRAPH_LOAD_MULTITHREAD 0 #else - #define UF_GRAPH_LOAD_MULTITHREAD 1 // causes Vulkan OOM + #define UF_GRAPH_LOAD_MULTITHREAD 1 +#endif + +#if UF_ENV_DREAMCAST + #define UF_DEBUG_TIMER_MULTITRACE_START(...) UF_TIMER_MULTITRACE_START(__VA_ARGS__) + #define UF_DEBUG_TIMER_MULTITRACE(...) UF_TIMER_MULTITRACE(__VA_ARGS__) + #define UF_DEBUG_TIMER_MULTITRACE_END(...) UF_TIMER_MULTITRACE_END(__VA_ARGS__) +#else + #define UF_DEBUG_TIMER_MULTITRACE_START(...) + #define UF_DEBUG_TIMER_MULTITRACE(...) + #define UF_DEBUG_TIMER_MULTITRACE_END(...) #endif namespace { @@ -308,15 +318,6 @@ namespace { } pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serializer& metadata ) { -#if UF_ENV_DREAMCAST - #define UF_DEBUG_TIMER_MULTITRACE_START(...) UF_TIMER_MULTITRACE_START(__VA_ARGS__) - #define UF_DEBUG_TIMER_MULTITRACE(...) UF_TIMER_MULTITRACE(__VA_ARGS__) - #define UF_DEBUG_TIMER_MULTITRACE_END(...) UF_TIMER_MULTITRACE_END(__VA_ARGS__) -#else - #define UF_DEBUG_TIMER_MULTITRACE_START(...) - #define UF_DEBUG_TIMER_MULTITRACE(...) - #define UF_DEBUG_TIMER_MULTITRACE_END(...) -#endif const uf::stl::string extension = uf::io::extension( filename ); #if UF_USE_GLTF if ( extension == "glb" || extension == "gltf" ) return ext::gltf::load( filename, metadata ); @@ -486,6 +487,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize DC_STATS(); #endif }); +#if 0 tasks.queue([&]{ // load animation information UF_DEBUG_TIMER_MULTITRACE("Reading animation information..."); @@ -518,6 +520,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize DC_STATS(); #endif }); +#endif tasks.queue([&]{ // load node information UF_DEBUG_TIMER_MULTITRACE("Reading nodes..."); diff --git a/engine/src/engine/graph/encode.cpp b/engine/src/engine/graph/encode.cpp index aa9e2854..17640360 100644 --- a/engine/src/engine/graph/encode.cpp +++ b/engine/src/engine/graph/encode.cpp @@ -440,7 +440,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string& if ( !settings.combined ) target = directory + "/graph.json"; serializer.writeToFile( target ); - UF_MSG_DEBUG("Saving graph to {}", target); + UF_MSG_DEBUG("Saved graph to {}", target); /* if ( graph.metadata["exporter"]["quit"].as(true) ) { diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 23ace1ac..e7324877 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -10,16 +10,27 @@ #include #include +#if UF_ENV_DREAMCAST + #define UF_DEBUG_TIMER_MULTITRACE_START(...) UF_TIMER_MULTITRACE_START(__VA_ARGS__) + #define UF_DEBUG_TIMER_MULTITRACE(...) UF_TIMER_MULTITRACE(__VA_ARGS__) + #define UF_DEBUG_TIMER_MULTITRACE_END(...) UF_TIMER_MULTITRACE_END(__VA_ARGS__) +#else + #define UF_DEBUG_TIMER_MULTITRACE_START(...) + #define UF_DEBUG_TIMER_MULTITRACE(...) + #define UF_DEBUG_TIMER_MULTITRACE_END(...) +#endif + namespace { bool newGraphAdded = true; ext::json::Value findTag( const uf::stl::string& tagName, const ext::json::Value& tags ) { ext::json::Value tag = ext::json::null(); - ext::json::forEach( tags, [&]( const uf::stl::string& key, const ext::json::Value& value ) { + ext::json::forEach( tags, [&]( const uf::stl::string& key, const ext::json::Value& value, bool& breaks ) { if ( uf::string::isRegex( key ) ) { if ( !uf::string::matched( tagName, key ) ) return; } else if ( tagName != key ) return; tag = value; + breaks = true; }); return tag; } @@ -410,7 +421,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M } // grab addresses - { + if ( uf::renderer::settings::pipelines::rt ) { pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer( mesh.indirect ).data(); for ( size_t drawID = 0; drawID < mesh.indirect.count; ++drawID ) { auto& drawCommand = drawCommands[drawID]; @@ -418,7 +429,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M auto instanceKeyName = std::to_string(instanceID); if ( uf::graph::storage.instanceAddresses.map.count(instanceKeyName) > 0 ) { - UF_MSG_DEBUG("DUPLICATE INSTANCE ID"); + UF_MSG_ERROR("DUPLICATE INSTANCE ID"); } auto& instanceAddresses = uf::graph::storage.instanceAddresses.map[instanceKeyName]; @@ -462,7 +473,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M } void uf::graph::process( pod::Graph& graph ) { - // copy our local storage to global storage + UF_DEBUG_TIMER_MULTITRACE_START("Processing {}", graph.name); // if ( !graph.root.entity ) graph.root.entity = new uf::Object; @@ -471,6 +482,8 @@ void uf::graph::process( pod::Graph& graph ) { uf::stl::unordered_map isSrgb; // process lightmap + + UF_DEBUG_TIMER_MULTITRACE("Parsing lightmaps"); { constexpr const char* UF_GRAPH_DEFAULT_LIGHTMAP = "./lightmap.%i.png"; uf::stl::unordered_map filenames; @@ -508,7 +521,7 @@ void uf::graph::process( pod::Graph& graph ) { auto time = uf::io::mtime(filename); if ( !uf::io::exists( filename ) ) continue; if ( time < mtime ) { - UF_MSG_DEBUG("Stale lightmap detected, disabling use of lightmaps: {}", filename); + UF_MSG_INFO("Stale lightmap detected, disabling use of lightmaps: {}", filename); stale = true; break; } @@ -572,6 +585,7 @@ void uf::graph::process( pod::Graph& graph ) { } // figure out what texture is what exactly + UF_DEBUG_TIMER_MULTITRACE("Determining format of textures"); for ( auto& key : graph.materials ) { auto& material = uf::graph::storage.materials[key]; auto ID = material.indexAlbedo; @@ -611,9 +625,16 @@ void uf::graph::process( pod::Graph& graph ) { // process nodes - for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity ); + UF_DEBUG_TIMER_MULTITRACE("Processing nodes"); + for ( auto index : graph.root.children ) { + process( graph, index, *graph.root.entity ); + + auto& node = graph.nodes[index]; + if ( node.entity ) UF_DEBUG_TIMER_MULTITRACE("Processed node: {}", node.name); + } // remap textures->images IDs + UF_DEBUG_TIMER_MULTITRACE("Remapping textures"); for ( auto& name : graph.textures ) { auto& texture = uf::graph::storage.textures[name]; auto& keys = uf::graph::storage.images.keys; @@ -636,7 +657,9 @@ void uf::graph::process( pod::Graph& graph ) { texture.index = it - keys.begin(); #endif } + // remap materials->texture IDs + UF_DEBUG_TIMER_MULTITRACE("Remapping materials"); for ( auto& name : graph.materials ) { auto& material = uf::graph::storage.materials[name]; auto& keys = uf::graph::storage.textures.keys; @@ -663,6 +686,7 @@ void uf::graph::process( pod::Graph& graph ) { } } // remap instance variables + UF_DEBUG_TIMER_MULTITRACE("Remapping instances"); for ( auto& name : graph.instances ) { auto& instance = uf::graph::storage.instances[name]; // auto& instanceAddresses = uf::graph::storage.instanceAddresses[name]; @@ -733,6 +757,7 @@ void uf::graph::process( pod::Graph& graph ) { } // patch materials/textures + UF_DEBUG_TIMER_MULTITRACE("Remapping patching/textures"); for ( auto& name : graph.materials ) { auto& material = uf::graph::storage.materials[name]; auto tag = ::findTag( name, graph ); @@ -766,10 +791,13 @@ void uf::graph::process( pod::Graph& graph ) { if ( graph.metadata["debug"]["print"]["materials"].as() ) for ( auto& name : graph.materials ) UF_MSG_DEBUG("Material: {}", name); if ( graph.metadata["debug"]["print"]["textures"].as() ) for ( auto& name : graph.textures ) UF_MSG_DEBUG("Texture: {}", name); + UF_DEBUG_TIMER_MULTITRACE("Updating master graph"); uf::graph::reload(); // setup combined mesh if requested if ( !(graph.metadata["renderer"]["separate"].as()) ) { + UF_DEBUG_TIMER_MULTITRACE("Processing root graphic"); + graph.root.mesh = graph.meshes.size(); auto keyName = graph.name + "/" + graph.root.name; auto& mesh = uf::graph::storage.meshes[graph.meshes.emplace_back(keyName)]; @@ -834,17 +862,27 @@ void uf::graph::process( pod::Graph& graph ) { } uf::graph::storage.instanceAddresses.keys = uf::graph::storage.instances.keys; - + UF_DEBUG_TIMER_MULTITRACE_END("Processed graph."); } void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) { auto& node = graph.nodes[index]; + // + bool ignore = false; // ignore pesky light_Orientation nodes - if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) return; + if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) ignore = true; // for dreamcast, ignore lights if we're baked - if ( graph.metadata["lights"]["lightmapped"].as() && graph.metadata["lights"]["disable if lightmapped"].as(true) ) if ( graph.lights.count(node.name) > 0 ) return; - - - // create child if requested + if ( graph.metadata["lights"]["lightmapped"].as() && graph.metadata["lights"]["disable if lightmapped"].as(true) ) if ( graph.lights.count(node.name) > 0 ) ignore = true; + + // on systems where frametime is very, very important, we can set all static nodes to not tick + + ext::json::Value tag = ::findTag( node.name, graph ); + if ( ext::json::isObject( tag ) ) { + if ( graph.metadata["baking"]["enabled"].as(false) && !tag["bake"].as(true) ) ignore = true; + if ( tag["ignore"].as() ) ignore = true; + } + if ( ignore ) return; + + // create child uf::Object* pointer = new uf::Object; parent.addChild(*pointer); @@ -856,15 +894,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) auto& metadataJson = entity.getComponent(); metadataJson["system"]["graph"]["name"] = node.name; metadataJson["system"]["graph"]["index"] = index; - - // on systems where frametime is very, very important, we can set all static nodes to not tick - - // tie to tag - ext::json::Value tag = ::findTag( node.name, graph ); - if ( ext::json::isObject( tag ) ) { - if ( tag["ignore"].as() ) return; - if ( graph.metadata["baking"]["enabled"].as(false) && !tag["bake"].as(true) ) return; + if ( ext::json::isObject( tag ) ) { if ( tag["action"].as() == "load" ) { if ( tag["filename"].is() ) { uf::stl::string filename = uf::io::resolveURI( tag["filename"].as(), graph.metadata["root"].as() ); @@ -878,18 +909,25 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) uf::stl::string filename = uf::io::resolveURI( tag["filename"].as(), graph.metadata["root"].as() ); auto& child = entity.loadChild( filename, false ); auto& childTransform = child.getComponent>(); + 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; + // childTransform.position = flatten.position; + // childTransform.orientation = flatten.orientation; + // childMetadataJson["transform"] = uf::transform::encode( flatten ); } if ( tag["static"].is() ) { metadata.system.ignoreGraph = tag["static"].as(); } } + // create as light { if ( graph.lights.count(node.name) > 0 ) { auto& l = graph.lights[node.name]; + #if UF_USE_OPENGL metadata.system.ignoreGraph = true; #else @@ -905,6 +943,10 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) metadataLight["color"][2] = l.color.z; metadataLight["shadows"] = graph.metadata["lights"]["shadows"].as(); + if ( uf::string::matched( node.name, "/\\bspot\\b/" ) ) { + metadataLight["type"] = "spot"; + } + if ( ext::json::isArray( graph.metadata["lights"]["radius"] ) ) { metadataLight["radius"] = graph.metadata["lights"]["radius"]; } @@ -930,13 +972,21 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) { metadataJson["light"][key] = value; }); + /* + if ( metadataJson["light"]["type"].as() == "point" ) { + auto& transform = entity.getComponent>(); + transform.orientation = uf::quaternion::identity(); + } + */ } #endif } } // set name - if ( setName ) entity.setName( node.name ); + if ( setName ) { + entity.setName( node.name ); + } // reference transform to parent auto& transform = entity.getComponent>(); @@ -1091,6 +1141,23 @@ void uf::graph::initialize( pod::Graph& graph ) { if ( entity->getUid() == 0 ) entity->initialize(); }); + auto& scene = uf::scene::getCurrentScene(); + scene.invalidateGraph(); + +/* + uf::renderer::states::rebuild = true; + + graph.root.entity->queueHook("system:Renderer.QueueRebuild", 2.0f); + + auto& scene = uf::scene::getCurrentScene(); + auto& controller = scene.getController(); + auto& transform = controller.getComponent>(); + auto& camera = controller.getComponent(); + + transform.orientation = uf::quaternion::identity(); + camera.getTransform().orientation = uf::quaternion::identity(); + camera.update(true); +*/ } void uf::graph::animate( pod::Graph& graph, const uf::stl::string& _name, float speed, bool immediate ) { if ( !(graph.metadata["renderer"]["skinned"].as()) ) return; @@ -1217,20 +1284,20 @@ void uf::graph::destroy( pod::Graph& graph ) { #endif } -void uf::graph::initialize() { #if UF_ENV_DREAMCAST - const size_t MAX_SIZE = 256; + size_t uf::graph::initialBufferElements = 256; #else - const size_t MAX_SIZE = 1024; + size_t uf::graph::initialBufferElements = 1024; #endif +void uf::graph::initialize() { uf::graph::storage.buffers.camera.initialize( (const void*) nullptr, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM ); - uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.instanceAddresses.initialize( (const void*) nullptr, sizeof(pod::Instance::Addresses) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.material.initialize( (const void*) nullptr, sizeof(pod::Material) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.texture.initialize( (const void*) nullptr, sizeof(pod::Texture) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); - uf::graph::storage.buffers.light.initialize( (const void*) nullptr, sizeof(pod::Light) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.instanceAddresses.initialize( (const void*) nullptr, sizeof(pod::Instance::Addresses) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.material.initialize( (const void*) nullptr, sizeof(pod::Material) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.texture.initialize( (const void*) nullptr, sizeof(pod::Texture) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.light.initialize( (const void*) nullptr, sizeof(pod::Light) * uf::graph::initialBufferElements, uf::renderer::enums::Buffer::STORAGE ); } void uf::graph::tick() { /* @@ -1238,15 +1305,16 @@ void uf::graph::tick() { for ( auto& key : uf::graph::storage.instances.keys ) instances.emplace_back( uf::graph::storage.instances.map[key] ); if ( !instances.empty() ) uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); */ + bool rebuild = false; uf::stl::vector instances = uf::graph::storage.instances.flatten(); - uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); + rebuild = rebuild || uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ); /* uf::stl::vector instanceAddresses; instanceAddresses.reserve(uf::graph::storage.instanceAddresses.map.size()); for ( auto& key : uf::graph::storage.instances.keys ) instanceAddresses.emplace_back( uf::graph::storage.instanceAddresses.map[key] ); - if ( !instanceAddresses.empty() ) uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ); + if ( !instanceAddresses.empty() ) rebuild = rebuild || uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ); */ uf::stl::vector instanceAddresses = uf::graph::storage.instanceAddresses.flatten(); - uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ); + rebuild = rebuild || uf::graph::storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ); uf::stl::vector joints; joints.reserve(uf::graph::storage.joints.map.size()); for ( auto& key : uf::graph::storage.joints.keys ) { @@ -1254,7 +1322,7 @@ void uf::graph::tick() { joints.reserve( joints.size() + matrices.size() ); for ( auto& mat : matrices ) joints.emplace_back( mat ); } - /*if ( !joints.empty() )*/ uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) ); + /*if ( !joints.empty() )*/ rebuild = rebuild || uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) ); if ( ::newGraphAdded ) { #if 1 @@ -1272,11 +1340,16 @@ void uf::graph::tick() { for ( auto& key : uf::graph::storage.materials.keys ) materials.emplace_back( uf::graph::storage.materials.map[key] ); for ( auto& key : uf::graph::storage.textures.keys ) textures.emplace_back( uf::graph::storage.textures.map[key] ); #endif - uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ); - uf::graph::storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ); - uf::graph::storage.buffers.texture.update( (const void*) textures.data(), textures.size() * sizeof(pod::Texture) ); + rebuild = rebuild || uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ); + rebuild = rebuild || uf::graph::storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ); + rebuild = rebuild || uf::graph::storage.buffers.texture.update( (const void*) textures.data(), textures.size() * sizeof(pod::Texture) ); ::newGraphAdded = false; + + if ( rebuild ) { + UF_MSG_DEBUG("Graph buffers requesting renderer update"); + uf::renderer::states::rebuild = true; + } } } void uf::graph::render() { @@ -1284,28 +1357,31 @@ void uf::graph::render() { auto& controller = scene.getController(); auto& camera = controller.getComponent(); -#if 0 - { - static uf::Entity* lastController = NULL; - if ( lastController == &controller ) return; - lastController = &controller; + + + uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) ); - uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) ); - } -#endif #if UF_USE_VULKAN auto* renderMode = uf::renderer::getCurrentRenderMode(); if ( !renderMode ) return; +/* + TIMER(1, renderMode->getType() == "Deferred") { + UF_MSG_DEBUG("{}: {}", renderMode->getName(), renderMode->getType()); + UF_MSG_DEBUG("{}: {}", controller.getName(), controller.getUid()); + UF_MSG_DEBUG("\tTransform[0]: {}", uf::transform::toString( controller.getComponent>() )); + UF_MSG_DEBUG("\tTransform[1]: {}", uf::transform::toString( camera.getTransform() )); + UF_MSG_DEBUG("\tMatrix: {}", uf::matrix::toString( camera.data().viewport.matrices[0].view )); + } +*/ for ( auto& buffer : renderMode->buffers ) { if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue; if ( buffer.allocationInfo.size != sizeof(pod::Camera::Viewports) ) continue; + if ( buffer.buffer == uf::graph::storage.buffers.camera.buffer ) continue; buffer.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) ); return; } #endif - - uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) ); } void uf::graph::destroy() { // cleanup graphic handles @@ -1326,6 +1402,8 @@ void uf::graph::destroy() { uf::graph::storage.buffers.texture.destroy(); uf::graph::storage.buffers.light.destroy(); + uf::renderer::states::rebuild = true; + // cleanup storage cache uf::graph::storage.instances.clear(); uf::graph::storage.instanceAddresses.clear(); diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 6619f948..f74325c6 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -217,8 +217,10 @@ void uf::ObjectBehavior::tick( uf::Object& self ) { } auto& queue = metadata.hooks.queue; - if ( !uf::Object::timer.running() ) uf::Object::timer.start(); - double curTime = uf::Object::timer.elapsed().asDouble(); + +// if ( !uf::Object::timer.running() ) uf::Object::timer.start(); +// double curTime = uf::Object::timer.elapsed().asDouble(); + auto curTime = uf::time::current; decltype(metadata.hooks.queue) unprocessed; unprocessed.reserve( metadata.hooks.queue.size() ); @@ -226,7 +228,10 @@ void uf::ObjectBehavior::tick( uf::Object& self ) { decltype(metadata.hooks.queue) executeQueue; executeQueue.reserve( metadata.hooks.queue.size() ); - for ( auto& q : queue ) if ( q.timeout < curTime ) executeQueue.emplace_back(q); else unprocessed.emplace_back(q); + for ( auto& q : queue ) { + if ( q.timeout < curTime ) executeQueue.emplace_back(q); + else unprocessed.emplace_back(q); + } for ( auto& q : executeQueue ) { if ( q.type == 1 ) this->callHook( q.name, q.userdata ); else if ( q.type == -1 ) this->callHook( q.name, q.json ); diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index cae5c983..5ee5936d 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -39,25 +39,31 @@ 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 ); } +void uf::Object::queueHook( const uf::stl::string& name, double timeout ) { + return queueHook( name, (float) timeout ); +} void uf::Object::queueHook( const uf::stl::string& name, float timeout ) { - if ( !uf::Object::timer.running() ) uf::Object::timer.start(); - double start = uf::Object::timer.elapsed().asDouble(); +// if ( !uf::Object::timer.running() ) uf::Object::timer.start(); +// double start = uf::Object::timer.elapsed().asDouble(); auto& metadata = this->getComponent(); auto& queue = metadata.hooks.queue.emplace_back(uf::ObjectBehavior::Metadata::Queued{ .name = name, - .timeout = start + timeout, + .timeout = uf::time::current + timeout, .type = 0, }); } +void uf::Object::queueHook( const uf::stl::string& name, const ext::json::Value& payload, double timeout ) { + return queueHook( name, payload, (float) timeout ); +} void uf::Object::queueHook( const uf::stl::string& name, const ext::json::Value& payload, float timeout ) { - if ( !uf::Object::timer.running() ) uf::Object::timer.start(); - double start = uf::Object::timer.elapsed().asDouble(); +// if ( !uf::Object::timer.running() ) uf::Object::timer.start(); +// double start = uf::Object::timer.elapsed().asDouble(); auto& metadata = this->getComponent(); auto& queue = metadata.hooks.queue.emplace_back(uf::ObjectBehavior::Metadata::Queued{ .name = name, - .timeout = start + timeout, + .timeout = uf::time::current + timeout, .type = -1, }); queue.json = payload; diff --git a/engine/src/engine/scene/behavior.cpp b/engine/src/engine/scene/behavior.cpp index 7927d81a..701ee8fc 100644 --- a/engine/src/engine/scene/behavior.cpp +++ b/engine/src/engine/scene/behavior.cpp @@ -10,7 +10,22 @@ void uf::SceneBehavior::initialize( uf::Object& self ) { uf::renderer::states::rebuild = true; this->addHook( "system:Renderer.QueueRebuild", [&](){ + // uf::renderer::states::resized = true; // crash uf::renderer::states::rebuild = true; + + /* + auto& renderMode = uf::renderer::getRenderMode("", true); + renderMode.rebuild = true; + + auto& scene = uf::scene::getCurrentScene(); + auto& controller = scene.getController(); + auto& transform = controller.getComponent>(); + auto& camera = controller.getComponent(); + + transform.orientation = uf::quaternion::identity(); + camera.getTransform().orientation = uf::quaternion::identity(); + camera.update(true); + */ }); this->addHook( "system:Destroy", [&](pod::payloads::Entity& payload){ if ( !payload.pointer ) { diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index f0047368..03165fba 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -101,7 +101,14 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::stl::str uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene; uf::scene::scenes.emplace_back( scene ); +#if UF_USE_FMT + uf::stl::string filename = _filename; + if ( _filename == "" ) { + filename = ::fmt::format("/{}/scene.json", uf::string::lowercase(name)); + } +#else const uf::stl::string filename = _filename != "" ? _filename : (uf::stl::string("/") + uf::string::lowercase(name) + "/scene.json"); +#endif scene->load(filename); if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene ); if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene ); diff --git a/engine/src/ext/bullet/bullet.cpp b/engine/src/ext/bullet/bullet.cpp index 6f7d8b4b..5d30d5dc 100644 --- a/engine/src/ext/bullet/bullet.cpp +++ b/engine/src/ext/bullet/bullet.cpp @@ -197,7 +197,7 @@ void ext::bullet::tick( float delta ) { if ( delta == 0.0f ) delta = uf::physics } */ ext::bullet::syncFrom(); - TIMER(ext::bullet::debugDrawRate, ext::bullet::debugDrawEnabled && ) { + TIMER(ext::bullet::debugDrawRate, ext::bullet::debugDrawEnabled ) { ext::bullet::dynamicsWorld->debugDrawWorld(); } } diff --git a/engine/src/ext/gltf/processPrimitives.inl b/engine/src/ext/gltf/processPrimitives.inl index b25b3175..44b15219 100644 --- a/engine/src/ext/gltf/processPrimitives.inl +++ b/engine/src/ext/gltf/processPrimitives.inl @@ -129,7 +129,7 @@ for ( auto& p : m.primitives ) { // required due to reverse-Z projection matrix flipping the X axis as well // default is to proceed with this - if ( !(graph.metadata["renderer"].as(true)) ){ + if ( graph.metadata["renderer"]["invert"].as(true) ){ vertex.position.x = -vertex.position.x; vertex.normal.x = -vertex.normal.x; #if UF_GRAPH_PROCESS_PRIMITIVES_FULL diff --git a/engine/src/ext/reactphysics/reactphysics.cpp b/engine/src/ext/reactphysics/reactphysics.cpp index 8af0065e..01d5fcd5 100644 --- a/engine/src/ext/reactphysics/reactphysics.cpp +++ b/engine/src/ext/reactphysics/reactphysics.cpp @@ -238,7 +238,7 @@ void ext::reactphysics::tick( float delta ) { } #endif - TIMER(ext::reactphysics::debugDraw::rate, ext::reactphysics::debugDraw::enabled && ) { + TIMER(ext::reactphysics::debugDraw::rate, ext::reactphysics::debugDraw::enabled ) { auto& scene = uf::scene::getCurrentScene(); ::debugDraw( scene ); } diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index 3feed137..e4e2cf6f 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -975,7 +975,7 @@ void ext::vulkan::Device::initialize() { queueInfo.pQueuePriorities = &defaultQueuePriority; queueCreateInfos.push_back(queueInfo); } else { - queueFamilyIndices.graphics = NULL; // VK_NULL_HANDLE; + queueFamilyIndices.graphics = 0; // VK_NULL_HANDLE; } // Dedicated compute queue if ( requestedQueueTypes & VK_QUEUE_COMPUTE_BIT ) { diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 74f0ade0..287d7b08 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -360,6 +360,7 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes renderTarget.renderPass, 0 ); + pipelineCreateInfo.pVertexInputState = &vertexInputState; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; pipelineCreateInfo.pRasterizationState = &rasterizationState; @@ -1834,25 +1835,6 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD size_t index = 0; } index, indirect; -/* - if ( descriptor.inputs.index.count && !descriptor.inputs.index.attributes.empty() ) { - auto& attribute = descriptor.inputs.index.attributes.front(); - // bool isInterleaved = 0 <= descriptor.inputs.index.interleaved; - // index.buffer = buffers.at((isInterleaved ? descriptor.inputs.index.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer; - // index.offset = isInterleaved ? descriptor.inputs.index.offset : attribute.offset; - // index.buffer = buffers.at(attribute.buffer + descriptor.inputs.bufferOffset).buffer; - // index.offset = attribute.offset; - } - if ( descriptor.inputs.indirect.count && !descriptor.inputs.indirect.attributes.empty() ) { - auto& attribute = descriptor.inputs.indirect.attributes.front(); - // bool isInterleaved = 0 <= descriptor.inputs.indirect.interleaved; - // indirect.buffer = buffers.at((isInterleaved ? descriptor.inputs.indirect.interleaved : attribute.buffer) + descriptor.inputs.bufferOffset).buffer; - // indirect.offset = isInterleaved ? descriptor.inputs.indirect.offset : attribute.offset; - // indirect.buffer = buffers.at(attribute.buffer + descriptor.inputs.bufferOffset).buffer; - // indirect.offset = attribute.offset; - } -*/ - for ( auto& buffer : buffers ) { if ( !index.buffer && buffer.usage & uf::renderer::enums::Buffer::INDEX ) index.buffer = buffer.buffer; if ( !indirect.buffer && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect.buffer = buffer.buffer; diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index eda98348..3b8b21ff 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -174,12 +174,19 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layer ext::vulkan::GraphicDescriptor ext::vulkan::RenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) { ext::vulkan::GraphicDescriptor descriptor = reference; -// descriptor.renderMode = this->getName(); descriptor.subpass = pass; descriptor.pipeline = metadata.pipeline; descriptor.inputs.width = this->width ? this->width : settings::width; descriptor.inputs.height = this->height ? this->height : settings::height; descriptor.parse( metadata.json["descriptor"] ); + +// descriptor.renderMode = this->getName(); + // invalidate + if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) { + descriptor.invalidated = true; + } else { + descriptor.renderMode = this->getName(); + } return descriptor; } @@ -234,6 +241,15 @@ void ext::vulkan::RenderMode::unlockMutex( std::thread::id id ) { std::lock_guard ext::vulkan::RenderMode::guardMutex( std::thread::id id ) { return this->commands.guardMutex( id ); } +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()); + pair.second.clear(); + } + container.clear(); +} void ext::vulkan::RenderMode::cleanupCommands( std::thread::id id ) { auto& container = this->commands.container(); for ( auto& pair : container ) { @@ -345,6 +361,10 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { } void ext::vulkan::RenderMode::tick() { + if ( ext::vulkan::states::resized || uf::renderer::states::rebuild || rebuild ) { + cleanupAllCommands(); + } + this->synchronize(); } @@ -382,7 +402,59 @@ void ext::vulkan::RenderMode::synchronize( uint64_t timeout ) { unlockMutex(); */ } -void ext::vulkan::RenderMode::pipelineBarrier( VkCommandBuffer command, uint8_t stage ) { +void ext::vulkan::RenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) { + VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + for ( auto& attachment : renderTarget.attachments ) { + if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; + if ( (attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; + + VkPipelineStageFlags srcStageMask, dstStageMask; + imageMemoryBarrier.image = attachment.image; + imageMemoryBarrier.oldLayout = attachment.descriptor.layout; + imageMemoryBarrier.newLayout = attachment.descriptor.layout; + + switch ( state ) { + case 0: { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } break; + case 1: { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageMemoryBarrier.newLayout = attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } break; + // ensure + default: { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + } + } + + vkCmdPipelineBarrier( commandBuffer, + srcStageMask, dstStageMask, + VK_FLAGS_NONE, + 0, NULL, + 0, NULL, + 1, &imageMemoryBarrier + ); + + attachment.descriptor.layout = imageMemoryBarrier.newLayout; + } } #endif \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index 418fdd23..60192fb8 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -21,21 +21,51 @@ const uf::stl::string ext::vulkan::BaseRenderMode::getType() const { return "Swapchain"; } void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector& graphics ) { - if ( ext::vulkan::renderModes.size() > 1 ) return; +// if ( ext::vulkan::renderModes.size() > 1 ) return; auto windowSize = device->window->getSize(); float width = windowSize.x; //this->width > 0 ? this->width : windowSize.x; float height = windowSize.y; //this->height > 0 ? this->height : windowSize.y; - VkCommandBufferBeginInfo commandBufferInfo = {}; - commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - commandBufferInfo.pNext = nullptr; + VkCommandBufferBeginInfo cmdBufInfo = {}; + cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmdBufInfo.pNext = nullptr; - // Set clear values for all framebuffer attachments with loadOp set to clear - // We use two attachments (color and depth) that are cleared at the start of the subpass and as such we need to set clear values for both - VkClearValue clearValues[2]; - clearValues[0].color = { { 0, 0, 0, 0 } }; - clearValues[1].depthStencil = { 0.0f, 0 }; + VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + uf::stl::vector layers = ext::vulkan::getRenderModes(uf::stl::vector{"RenderTarget", "Compute", "Deferred"}, false); + if ( !settings::pipelines::rt ) { + std::reverse( layers.begin(), layers.end() ); + } + + auto& scene = uf::scene::getCurrentScene(); + auto& sceneMetadataJson = scene.getComponent(); + auto& commands = getCommands(); + + uf::stl::vector clearValues; + for ( auto& attachment : renderTarget.attachments ) { + pod::Vector4f clearColor = uf::vector::decode( sceneMetadataJson["system"]["renderer"]["clear values"][(int) clearValues.size()], pod::Vector4f{0, 0, 0, 0} ); + auto& clearValue = clearValues.emplace_back(); + if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + clearValue.color.float32[0] = clearColor[0]; + clearValue.color.float32[1] = clearColor[1]; + clearValue.color.float32[2] = clearColor[2]; + clearValue.color.float32[3] = clearColor[3]; + } else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { + if ( uf::matrix::reverseInfiniteProjection ) { + clearValue.depthStencil = { 0.0f, 0 }; + } else { + clearValue.depthStencil = { 1.0f, 0 }; + } + } + } VkRenderPassBeginInfo renderPassBeginInfo = {}; renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -45,47 +75,139 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vectorrecord(commands[i] ); + vkCmdPipelineBarrier(commands[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + } + + // transition layers for read + /* + for ( auto layer : layers ) { + layer->pipelineBarrier( commands[i], 0 ); + } + */ + for ( auto _ : layers ) { + RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; + auto& blitter = layer->blitter; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.renderMode != this->getName() ) continue; + layer->pipelineBarrier( commands[i], 0 ); } - vkCmdEndRenderPass(commands[i]); - // Ending the render pass will add an implicit barrier transitioning the frame buffer color attachment to - // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR for presenting it to the windowing system + // pre-renderpass commands + if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] ); + vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commands[i], 0, 1, &viewport); + vkCmdSetScissor(commands[i], 0, 1, &scissor); + // render to geometry buffers + for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { + size_t currentPass = 0; + size_t currentDraw = 0; + + // blit any RT's that request this subpass + for ( auto _ : layers ) { + RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; + auto& blitter = layer->blitter; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass || blitter.descriptor.renderMode != this->getName() ) continue; + // UF_MSG_DEBUG("`{}`: {} | `{}` | {} | {} | {}", layer->getName(), layer->getType(), blitter.descriptor.renderMode, blitter.initialized, blitter.process, blitter.descriptor.subpass); + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; // bindGraphicDescriptor(blitter.descriptor, currentSubpass); + blitter.record(commands[i], descriptor); + } + } + vkCmdEndRenderPass(commands[i]); + + // post-renderpass commands + if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] ); + + // need to transfer it back, if they differ + if ( ext::vulkan::device.queueFamilyIndices.graphics != ext::vulkan::device.queueFamilyIndices.present ) { + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + imageMemoryBarrier.oldLayout = renderTarget.attachments[i].descriptor.layout; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imageMemoryBarrier.srcQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics; + imageMemoryBarrier.dstQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.present; + imageMemoryBarrier.image = renderTarget.attachments[i].image; + + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout; + + vkCmdPipelineBarrier(commands[i], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + } + + for ( auto _ : layers ) { + RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; + auto& blitter = layer->blitter; + if ( !blitter.initialized || !blitter.process || blitter.descriptor.renderMode != this->getName() ) continue; + layer->pipelineBarrier( commands[i], 1 ); + } + /* + for ( auto layer : layers ) { + layer->pipelineBarrier( commands[i], 1 ); + } + */ + } VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); } } void ext::vulkan::BaseRenderMode::tick() { ext::vulkan::RenderMode::tick(); + if ( ext::vulkan::states::resized ) { this->destroy(); this->initialize( *this->device ); @@ -93,7 +215,7 @@ void ext::vulkan::BaseRenderMode::tick() { } void ext::vulkan::BaseRenderMode::render() { // if ( ext::vulkan::renderModes.size() > 1 ) return; - if ( ext::vulkan::renderModes.back() != this ) return; +// if ( ext::vulkan::renderModes.back() != this ) return; //lockMutex( this->mostRecentCommandPoolId ); auto& commands = getCommands( this->mostRecentCommandPoolId ); @@ -179,7 +301,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) { VK_CHECK_RESULT(vkCreateImageView( device, &colorAttachmentView, nullptr, &renderTarget.attachments[i].view)); renderTarget.attachments[i].descriptor.format = ext::vulkan::settings::formats::color; - renderTarget.attachments[i].descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + renderTarget.attachments[i].descriptor.layout = VK_IMAGE_LAYOUT_UNDEFINED; renderTarget.attachments[i].descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; renderTarget.attachments[i].descriptor.aliased = true; renderTarget.attachments[i].image = images[i]; @@ -350,6 +472,33 @@ 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); + for ( size_t i = 0; i < images.size(); ++i ) { + VkImageMemoryBarrier imageMemoryBarrier = {}; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + imageMemoryBarrier.oldLayout = renderTarget.attachments[i].descriptor.layout; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.present; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; + + imageMemoryBarrier.image = renderTarget.attachments[i].image; + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + renderTarget.attachments[i].descriptor.layout = imageMemoryBarrier.newLayout; + + 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); + } +#endif /* { renderTarget.device = &device; @@ -423,4 +572,21 @@ void ext::vulkan::BaseRenderMode::destroy() { } } +ext::vulkan::GraphicDescriptor ext::vulkan::BaseRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) { + ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass); +/* + descriptor.parse(metadata.json["descriptor"]); + // invalidate + if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) { + descriptor.invalidated = true; + } else { + descriptor.renderMode = this->getName(); + } +*/ + + descriptor.depth.test = false; + descriptor.depth.write = false; + return descriptor; +} + #endif \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/compute.cpp b/engine/src/ext/vulkan/rendermodes/compute.cpp index bce0770f..eb1e3074 100644 --- a/engine/src/ext/vulkan/rendermodes/compute.cpp +++ b/engine/src/ext/vulkan/rendermodes/compute.cpp @@ -35,14 +35,15 @@ uf::stl::vector ext::vulkan::ComputeRenderMode::getBlitte ext::vulkan::GraphicDescriptor ext::vulkan::ComputeRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) { ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass); +/* descriptor.parse(metadata.json["descriptor"]); - // invalidate if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) { descriptor.invalidated = true; } else { descriptor.renderMode = this->getName(); } +*/ return descriptor; } diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index 03a09a27..417d5489 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -106,7 +106,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{ /*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT, /*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - /*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + /*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, /*.blend =*/ blend, /*.samples =*/ 1, }); @@ -124,6 +124,9 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.blend =*/ blend, /*.samples =*/ 1, }); + UF_MSG_DEBUG("{} = {}", "color", attachments.color); + UF_MSG_DEBUG("{} = {}", "bright", attachments.bright); + UF_MSG_DEBUG("{} = {}", "scratch", attachments.scratch); // Attach swapchain's image as output if ( settings::invariant::deferredAliasOutputToSwapchain ) { @@ -233,33 +236,80 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { 0, 1, 2, 2, 3, 0 }); */ + auto& scene = uf::scene::getCurrentScene(); + auto& sceneMetadataJson = scene.getComponent(); - blitter.descriptor.subpass = 1; + blitter.descriptor.renderMode = "Swapchain"; + blitter.descriptor.subpass = 0; blitter.descriptor.depth.test = false; blitter.descriptor.depth.write = false; - blitter.initialize( this->getName() ); + blitter.initialize( "Swapchain" ); blitter.initializeMesh( mesh ); - uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/subpass.vert.spv"; - uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/subpass.frag.spv"; { - std::pair settings[] = { - { uf::renderer::settings::pipelines::vxgi, "vxgi.frag" }, - { msaa > 1, "msaa.frag" }, - { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" }, - { uf::renderer::settings::pipelines::rt, "rt.frag" }, - }; - FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); + { + uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/renderTargetSimple.vert.spv"; + uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTargetSimple.frag.spv"; { + std::pair settings[] = { + { msaa > 1, "msaa.frag" }, + // I don't actually have support for deferred sampling within a render target + // { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" }, + }; + FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); + } + blitter.material.initializeShaders({ + {uf::io::resolveURI(vertexShaderFilename), uf::renderer::enums::Shader::VERTEX}, + {uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT} + }); } - UF_MSG_DEBUG("Using fragment shader: {}", fragmentShaderFilename); - blitter.material.initializeShaders({ - {uf::io::resolveURI(vertexShaderFilename), VK_SHADER_STAGE_VERTEX_BIT}, - {uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT} - }); - - auto& scene = uf::scene::getCurrentScene(); - auto& sceneMetadataJson = scene.getComponent(); + { + auto& shader = blitter.material.getShader("fragment"); + shader.textures.clear(); + shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]], (size_t) 0 ); // attachments.color + /* + for ( auto& texture : shader.textures ) { + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + */ + + /* + for ( auto& attachment : renderTarget.attachments ) { + if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; + + Texture2D& texture = shader.textures.emplace_back(); + enums::Filter::type_t filter = VK_FILTER_NEAREST; + + texture.sampler.descriptor.filter.min = filter; + texture.sampler.descriptor.filter.mag = filter; + texture.aliasAttachment(attachment); + } + */ + } + + if ( settings::pipelines::deferred ) { + uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/subpass.vert.spv"; + uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/subpass.frag.spv"; { + std::pair settings[] = { + { uf::renderer::settings::pipelines::vxgi, "vxgi.frag" }, + { msaa > 1, "msaa.frag" }, + { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" }, + { uf::renderer::settings::pipelines::rt, "rt.frag" }, + }; + FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second ); + } + UF_MSG_DEBUG("Using fragment shader: {}", fragmentShaderFilename); + + /* + blitter.material.initializeShaders({ + {uf::io::resolveURI(vertexShaderFilename), VK_SHADER_STAGE_VERTEX_BIT}, + {uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT} + }, "deferred"); + */ + blitter.material.attachShader(uf::io::resolveURI(vertexShaderFilename), uf::renderer::enums::Shader::VERTEX, "deferred"); + blitter.material.attachShader(uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT, "deferred"); + } if ( settings::pipelines::bloom ) { uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom.comp.spv"); @@ -276,8 +326,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { } } - { - auto& shader = blitter.material.getShader("fragment"); + if ( settings::pipelines::deferred ) { + auto& shader = blitter.material.getShader("fragment", "deferred"); size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as(512); size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); @@ -331,10 +381,24 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { } } } - for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { - auto descriptor = blitter.descriptor; - descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1; - if ( !blitter.hasPipeline( descriptor ) ) blitter.initializePipeline( descriptor ); + + if ( !blitter.hasPipeline( blitter.descriptor ) ){ + blitter.initializePipeline( blitter.descriptor ); + } + + { + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; + descriptor.renderMode = ""; + + if ( settings::pipelines::deferred ) { + for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { + descriptor.pipeline = "deferred"; + descriptor.subpass = 1; // (renderTarget.passes.size() / metadata.eyes) * eye + 1; + if ( !blitter.hasPipeline( descriptor ) ) { + blitter.initializePipeline( descriptor ); + } + } + } if ( settings::pipelines::bloom ) { descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 }; @@ -358,25 +422,58 @@ void ext::vulkan::DeferredRenderMode::tick() { if ( settings::pipelines::bloom ) { auto& shader = blitter.material.getShader("compute", "bloom"); - #if 1 shader.textures.clear(); - shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 5], (size_t) 0 ); // attachments.color - shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 4], (size_t) 0 ); // attachments.bright - shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 3], (size_t) 0 ); // attachments.scratch + shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]+0], (size_t) 0 ); // attachments.color + shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]+1], (size_t) 0 ); // attachments.bright + shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]+2], (size_t) 0 ); // attachments.scratch for ( auto& texture : shader.textures ) { texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - #endif } } // update blitter descriptor set if ( rebuild && blitter.initialized ) { - for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { - auto descriptor = blitter.descriptor; - descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1; - if ( blitter.hasPipeline( blitter.descriptor ) ) blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor ); - + { + auto& shader = blitter.material.getShader("fragment"); + shader.textures.clear(); + shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[metadata.outputs[0]], (size_t) 0 ); // attachments.color + /* + for ( auto& texture : shader.textures ) { + texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + */ + /* + for ( auto& attachment : renderTarget.attachments ) { + if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; + + Texture2D& texture = shader.textures.emplace_back(); + enums::Filter::type_t filter = VK_FILTER_NEAREST; + + texture.sampler.descriptor.filter.min = filter; + texture.sampler.descriptor.filter.mag = filter; + texture.aliasAttachment(attachment); + } + */ + } + + if ( blitter.hasPipeline( blitter.descriptor ) ){ + blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor ); + } + { + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; + descriptor.renderMode = ""; + if ( settings::pipelines::deferred ) { + for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { + descriptor.pipeline = "deferred"; + descriptor.subpass = 1; // (renderTarget.passes.size() / metadata.eyes) * eye + 1; + if ( blitter.hasPipeline( descriptor ) ) { + blitter.getPipeline( descriptor ).update( blitter, descriptor ); + } + } + } + if ( settings::pipelines::bloom ) { descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 }; descriptor.pipeline = "bloom"; @@ -407,6 +504,31 @@ VkSubmitInfo ext::vulkan::DeferredRenderMode::queue() { return submitInfo; } void ext::vulkan::DeferredRenderMode::render() { + if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{} ); + + //lockMutex( this->mostRecentCommandPoolId ); + auto& commands = getCommands( this->mostRecentCommandPoolId ); + // Submit commands + // Use a fence to ensure that command buffer has finished executing before using it again + VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX )); + VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] )); + + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at + submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.waitSemaphoreCount = 0; // One wait semaphore + submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed + submitInfo.signalSemaphoreCount = 0; // One signal semaphore + 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])); + + if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} ); + + this->executed = true; +#if 0 //lockMutex( this->mostRecentCommandPoolId ); auto& commands = getCommands( this->mostRecentCommandPoolId ); // Get next image in the swap chain (back/front buffer) @@ -440,7 +562,7 @@ void ext::vulkan::DeferredRenderMode::render() { VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT ))); this->executed = true; - +#endif //unlockMutex( this->mostRecentCommandPoolId ); } void ext::vulkan::DeferredRenderMode::destroy() { @@ -470,40 +592,34 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; uf::stl::vector layers = ext::vulkan::getRenderModes(uf::stl::vector{"RenderTarget", "Compute"}, false); + auto& scene = uf::scene::getCurrentScene(); - auto& sceneMetadata = scene.getComponent(); + auto& sceneMetadataJson = scene.getComponent(); + auto& commands = getCommands(); - auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain"); +// auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain"); + uf::stl::vector clearValues; + for ( auto& attachment : renderTarget.attachments ) { + pod::Vector4f clearColor = uf::vector::decode( sceneMetadataJson["system"]["renderer"]["clear values"][(int) clearValues.size()], pod::Vector4f{0, 0, 0, 0} ); + auto& clearValue = clearValues.emplace_back(); + if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + clearValue.color.float32[0] = clearColor[0]; + clearValue.color.float32[1] = clearColor[1]; + clearValue.color.float32[2] = clearColor[2]; + clearValue.color.float32[3] = clearColor[3]; + } else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { + if ( uf::matrix::reverseInfiniteProjection ) { + clearValue.depthStencil = { 0.0f, 0 }; + } else { + clearValue.depthStencil = { 1.0f, 0 }; + } + } + } + for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); // Fill GBuffer { - uf::stl::vector clearValues; - for ( auto& attachment : renderTarget.attachments ) { - VkClearValue clearValue; - if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { - if ( !ext::json::isNull( sceneMetadata["system"]["renderer"]["clear values"][(int) clearValues.size()] ) ) { - auto& v = sceneMetadata["system"]["renderer"]["clear values"][(int) clearValues.size()]; - clearValue.color = { { - v[0].as(), - v[1].as(), - v[2].as(), - v[3].as(), - } }; - } else { - clearValue.color = { { 0, 0, 0, 0 } }; - } - } else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { - if ( uf::matrix::reverseInfiniteProjection ) { - clearValue.depthStencil = { 0.0f, 0 }; - } else { - clearValue.depthStencil = { 1.0f, 0 }; - } - } - clearValues.push_back(clearValue); - } - // uf::matrix::reverseInfiniteProjection - // descriptor.depth.operation ext::RENDERER::enums::Compare::GREATER_OR_EQUAL VkRenderPassBeginInfo renderPassBeginInfo = {}; renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -530,13 +646,13 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto scissor.extent.height = height; scissor.offset.x = 0; scissor.offset.y = 0; + + size_t currentSubpass = 0; // transition layers for read for ( auto layer : layers ) { layer->pipelineBarrier( commands[i], 0 ); } - - size_t currentSubpass = 0; for ( auto& pipeline : metadata.pipelines ) { if ( pipeline == metadata.pipeline ) continue; @@ -547,6 +663,17 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto graphic->record( commands[i], descriptor, 0, metadata.eyes ); } } + /* + for ( auto& pipeline : metadata.pipelines ) { + if ( pipeline == metadata.pipeline || pipeline == "deferred" ) continue; + for ( auto graphic : graphics ) { + if ( graphic->descriptor.renderMode != this->getName() ) continue; + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); + descriptor.pipeline = pipeline; + graphic->record( commands[i], descriptor, 0, metadata.eyes ); + } + } + */ // pre-renderpass commands if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i] ); @@ -564,43 +691,56 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); graphic->record( commands[i], descriptor, eye, currentDraw++ ); } - // blit any RT's that request this subpass - { - for ( auto _ : layers ) { - RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; - auto& blitter = layer->blitter; - if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue; - ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); - blitter.record(commands[i], descriptor); - } - } vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass; ++currentSubpass; // deferred post-processing lighting pass if ( !settings::pipelines::rt ) { - ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; // = bindGraphicDescriptor(blitter.descriptor, currentSubpass); + descriptor.renderMode = ""; + descriptor.pipeline = "deferred"; + descriptor.subpass = 1; blitter.record(commands[i], descriptor, eye, currentDraw++); } - // blit any RT's that request this subpass - { - for ( auto _ : layers ) { - RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _; - auto& blitter = layer->blitter; - if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue; - ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); - blitter.record(commands[i], descriptor, eye, currentDraw++); - } - } if ( eye + 1 < metadata.eyes ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; } vkCmdEndRenderPass(commands[i]); + #if 0 + // fill GBuffer + vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commands[i], 0, 1, &viewport); + vkCmdSetScissor(commands[i], 0, 1, &scissor); + // render to geometry buffers + for ( size_t eye = 0; eye < metadata.eyes; ++eye ) { + size_t currentPass = 0; + size_t currentDraw = 0; + if ( !settings::pipelines::rt ) for ( auto graphic : graphics ) { + // only draw graphics that are assigned to this type of render mode + if ( graphic->descriptor.renderMode != this->getName() ) continue; + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); + graphic->record( commands[i], descriptor, eye, currentDraw++ ); + } + // if ( eye + 1 < metadata.eyes ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; + vkCmdEndRenderPass(commands[i]); + + // parse GBuffer + vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdSetViewport(commands[i], 0, 1, &viewport); + vkCmdSetScissor(commands[i], 0, 1, &scissor); + + ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; + descriptor.pipeline = "deferred"; + blitter.record(commands[i], descriptor, 0, 0); + vkCmdEndRenderPass(commands[i]); + #endif + // post-renderpass commands if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] ); + #if 1 if ( settings::pipelines::bloom ) { ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; - descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 }; descriptor.pipeline = "bloom"; + descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 }; descriptor.subpass = 0; auto& shader = blitter.material.getShader("compute", "bloom"); @@ -647,11 +787,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); } } + #endif for ( auto layer : layers ) { layer->pipelineBarrier( commands[i], 1 ); } - + #if 0 if ( !settings::invariant::deferredAliasOutputToSwapchain ) { { auto& renderTarget = swapchainRender.renderTarget; @@ -742,6 +883,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto } } } + #endif } VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 4ad5f11d..3c05d1e6 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -35,7 +35,15 @@ uf::stl::vector ext::vulkan::RenderTargetRenderMode::getB ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) { ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass); +/* descriptor.parse(metadata.json["descriptor"]); + // invalidate + if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) { + descriptor.invalidated = true; + } else { + descriptor.renderMode = this->getName(); + } +*/ if ( 0 <= pass && pass < metadata.subpasses && metadata.type == uf::renderer::settings::pipelines::names::vxgi ) { descriptor.cullMode = VK_CULL_MODE_NONE; @@ -44,12 +52,6 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD } else if ( metadata.type == "depth" ) { descriptor.cullMode = VK_CULL_MODE_NONE; } - // invalidate - if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) { - descriptor.invalidated = true; - } else { - descriptor.renderMode = this->getName(); - } return descriptor; } @@ -167,7 +169,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{ /*.format =*/ VK_FORMAT_R8G8B8A8_UNORM, /*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - /*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + /*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, /*.blend =*/ true, /*.samples =*/ 1, }); @@ -297,8 +299,8 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { // do not attach if we're requesting no blitter shaders blitter.process = false; } else { - uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/renderTarget.vert.spv"; - uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget.frag.spv"; { + uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/renderTargetSimple.vert.spv"; + uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTargetSimple.frag.spv"; { std::pair settings[] = { { msaa > 1, "msaa.frag" }, // I don't actually have support for deferred sampling within a render target @@ -412,7 +414,7 @@ void ext::vulkan::RenderTargetRenderMode::tick() { size_t eyes = mainRenderMode.metadata.eyes; for ( size_t eye = 0; eye < eyes; ++eye ) { ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; - descriptor.subpass = 2 * eye + 1; + descriptor.subpass = 0; // 2 * eye; // + 1; if ( !blitter.hasPipeline( descriptor ) ) { blitter.initializePipeline( descriptor ); } else { @@ -464,58 +466,7 @@ void ext::vulkan::RenderTargetRenderMode::render() { //unlockMutex( this->mostRecentCommandPoolId ); } void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) { - VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED - imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED - imageMemoryBarrier.subresourceRange.baseMipLevel = 0; - imageMemoryBarrier.subresourceRange.levelCount = 1; - imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; - imageMemoryBarrier.subresourceRange.layerCount = 1; - imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - for ( auto& attachment : renderTarget.attachments ) { - if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue; - if ( (attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - - VkPipelineStageFlags srcStageMask, dstStageMask; - imageMemoryBarrier.image = attachment.image; - imageMemoryBarrier.oldLayout = attachment.descriptor.layout; - imageMemoryBarrier.newLayout = attachment.descriptor.layout; - - switch ( state ) { - case 0: { - imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } break; - case 1: { - imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - imageMemoryBarrier.newLayout = attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - } break; - // ensure - default: { - imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - } - } - - vkCmdPipelineBarrier( commandBuffer, - srcStageMask, dstStageMask, - VK_FLAGS_NONE, - 0, NULL, - 0, NULL, - 1, &imageMemoryBarrier - ); - - attachment.descriptor.layout = imageMemoryBarrier.newLayout; - } + ext::vulkan::RenderMode::pipelineBarrier( commandBuffer, state ); } void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::vector& graphics ) { // destroy if exists @@ -525,26 +476,30 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v VkCommandBufferBeginInfo cmdBufInfo = {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.pNext = nullptr; + + auto& scene = uf::scene::getCurrentScene(); + auto& sceneMetadataJson = scene.getComponent(); + + uf::stl::vector clearValues; + for ( size_t j = 0; j < renderTarget.views; ++j ) { + for ( auto& attachment : renderTarget.attachments ) { + auto& clearValue = clearValues.emplace_back(); + if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { + clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; + } else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { + if ( uf::matrix::reverseInfiniteProjection ) { + clearValue.depthStencil = { 0.0f, 0 }; + } else { + clearValue.depthStencil = { 1.0f, 0 }; + } + } + } + } + auto& commands = getCommands(); for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); { - uf::stl::vector clearValues; - for ( size_t j = 0; j < renderTarget.views; ++j ) { - for ( auto& attachment : renderTarget.attachments ) { - VkClearValue clearValue; - if ( attachment.descriptor.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) { - clearValue.color = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - } else if ( attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) { - if ( uf::matrix::reverseInfiniteProjection ) { - clearValue.depthStencil = { 0.0f, 0 }; - } else { - clearValue.depthStencil = { 1.0f, 0 }; - } - } - clearValues.push_back(clearValue); - } - } VkRenderPassBeginInfo renderPassBeginInfo = {}; renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; diff --git a/engine/src/ext/vulkan/shader.cpp b/engine/src/ext/vulkan/shader.cpp index 44bb5b3d..875e9c7f 100644 --- a/engine/src/ext/vulkan/shader.cpp +++ b/engine/src/ext/vulkan/shader.cpp @@ -724,6 +724,8 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl size_t size = 4; uint8_t buffer[size]; + memset( &buffer[0], size, 0 ); + auto& definition = metadata.definitions.specializationConstants[name]; definition.name = name; definition.index = offset / size; diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 460afe49..055ba32d 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -53,6 +53,7 @@ bool ext::vulkan::settings::invariant::deferredSampling = true; bool ext::vulkan::settings::invariant::multiview = true; // pipelines +bool ext::vulkan::settings::pipelines::deferred = true; bool ext::vulkan::settings::pipelines::vsync = true; bool ext::vulkan::settings::pipelines::hdr = true; bool ext::vulkan::settings::pipelines::vxgi = true; @@ -60,6 +61,7 @@ bool ext::vulkan::settings::pipelines::culling = false; bool ext::vulkan::settings::pipelines::bloom = false; bool ext::vulkan::settings::pipelines::rt = false; +uf::stl::string ext::vulkan::settings::pipelines::names::deferred = "deferred"; uf::stl::string ext::vulkan::settings::pipelines::names::vsync = "vsync"; uf::stl::string ext::vulkan::settings::pipelines::names::hdr = "hdr"; uf::stl::string ext::vulkan::settings::pipelines::names::vxgi = "vxgi"; @@ -184,7 +186,8 @@ ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mo RenderMode& primary = getRenderMode("", true); auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); - } else { + } + { RenderMode& primary = getRenderMode("Swapchain", true); auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index 09b65219..3347374e 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -3,7 +3,7 @@ #include #define UF_XATLAS_UNWRAP_MULTITHREAD 1 -#define UF_XATLAS_LAZY 0 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it +#define UF_XATLAS_UNWRAP_SERIAL 1 // really big scenes will gorge on memory size_t UF_API ext::xatlas::unwrap( pod::Graph& graph ) { return graph.metadata["exporter"]["unwrap lazy"].as(false) ? unwrapLazy( graph ) : unwrapExperimental( graph ); @@ -20,8 +20,7 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { size_t vertexOffset = 0; }; - uf::stl::vector sources; - sources.reserve(graph.meshes.size()); + uf::stl::vector sources(graph.meshes.size()); uf::stl::unordered_map atlases; atlases.reserve(graph.meshes.size()); @@ -34,7 +33,8 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { for ( auto index = 0; index < graph.meshes.size(); ++index ) { auto& name = graph.meshes[index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - sources.emplace_back(mesh).updateDescriptor(); + auto& source = sources[index]; + if ( mesh.isInterleaved() ) { UF_EXCEPTION("unwrapping interleaved mesh is not supported"); } @@ -44,17 +44,20 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { should = true; } else { ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { - // if ( ext::json::isNull( value["unwrap mesh"] ) ) return; - if ( !value["unwrap mesh"].as(false) ) return; - if ( uf::string::isRegex( key ) ) { if ( !uf::string::matched( name, key ) ) return; } else if ( name != key ) return; + + if ( ext::json::isNull( value["unwrap mesh"] ) ) return; + if ( !value["unwrap mesh"].as(false) ) return; + should = true; }); } if ( !should ) continue; + source = mesh; + source.updateDescriptor(); uf::Mesh::Input vertexInput = mesh.vertex; @@ -131,21 +134,6 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { } else UF_EXCEPTION("to-do: not require indices for meshes"); } - // add mesh decls to mesh atlases - // done after the fact since we'll know the total amount of meshes added - for ( auto& pair : atlases ) { - auto& atlas = pair.second; - if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); - - for ( auto& entry : atlas.entries ) { - ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); - if (error != ::xatlas::AddMeshError::Success) { - ::xatlas::Destroy(atlas.pointer); - UF_EXCEPTION("{}", ::xatlas::StringForEnum(error)); - } - } - } - ::xatlas::ChartOptions chartOptions{}; chartOptions.useInputMeshUvs = graph.metadata["baking"]["settings"]["useInputMeshUvs"].as(chartOptions.useInputMeshUvs); chartOptions.maxIterations = graph.metadata["baking"]["settings"]["maxIterations"].as(chartOptions.maxIterations); @@ -162,6 +150,22 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { packOptions.rotateCharts = graph.metadata["baking"]["settings"]["rotateCharts"].as(packOptions.rotateCharts); packOptions.resolution = graph.metadata["baking"]["resolution"].as(packOptions.resolution); + // add mesh decls to mesh atlases + // done after the fact since we'll know the total amount of meshes added + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); + + for ( auto& entry : atlas.entries ) { + ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); + if (error != ::xatlas::AddMeshError::Success) { + ::xatlas::Destroy(atlas.pointer); + UF_EXCEPTION("{}", ::xatlas::StringForEnum(error)); + } + } + } + + // pack #if UF_XATLAS_UNWRAP_MULTITHREAD auto tasks = uf::thread::schedule(true); @@ -195,6 +199,9 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { for ( auto i = 0; i < graph.meshes.size(); ++i ) { auto& name = graph.meshes[i]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + auto& source = sources[i]; + if ( source.vertex.count == 0 ) continue; + if ( sizesVertex[i] != mesh.vertex.count ) { mesh.resizeVertices( sizesVertex[i] ); } @@ -213,6 +220,9 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { auto& name = graph.meshes[entry.index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; auto& source = sources[entry.index]; + + if ( source.vertex.count == 0 ) continue; + source.updateDescriptor(); // draw commands @@ -233,7 +243,9 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { for ( auto index = 0; index < graph.meshes.size(); ++index ) { auto& name = graph.meshes[index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - + auto& source = sources[index]; + + if ( source.vertex.count == 0 ) continue; if ( !mesh.indirect.count ) continue; auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; @@ -257,8 +269,9 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { // update vertices for ( auto& pair : atlases ) { - size_t vertexIDOffset = 0; auto& atlas = pair.second; + + size_t vertexIDOffset = 0; for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { auto& xmesh = atlas.pointer->meshes[i]; auto& entry = atlas.entries[i]; @@ -266,6 +279,7 @@ size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) { auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; auto& source = sources[entry.index]; + if ( source.vertex.count == 0 ) continue; // draw commands if ( mesh.indirect.count ) { @@ -398,12 +412,12 @@ size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) { should = true; } else { ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { - // if ( ext::json::isNull( value["unwrap mesh"] ) ) return; - if ( !value["unwrap mesh"].as(false) ) return; - if ( uf::string::isRegex( key ) ) { if ( !uf::string::matched( name, key ) ) return; } else if ( name != key ) return; + + if ( ext::json::isNull( value["unwrap mesh"] ) ) return; + if ( !value["unwrap mesh"].as(false) ) return; should = true; }); } @@ -485,21 +499,6 @@ size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) { } else UF_EXCEPTION("to-do: not require indices for meshes"); } - // add mesh decls to mesh atlases - // done after the fact since we'll know the total amount of meshes added - for ( auto& pair : atlases ) { - auto& atlas = pair.second; - if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); - - for ( auto& entry : atlas.entries ) { - ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); - if (error != ::xatlas::AddMeshError::Success) { - ::xatlas::Destroy(atlas.pointer); - UF_EXCEPTION("{}", ::xatlas::StringForEnum(error)); - } - } - } - ::xatlas::ChartOptions chartOptions{}; chartOptions.useInputMeshUvs = graph.metadata["baking"]["settings"]["useInputMeshUvs"].as(chartOptions.useInputMeshUvs); chartOptions.maxIterations = graph.metadata["baking"]["settings"]["maxIterations"].as(chartOptions.maxIterations); @@ -517,6 +516,77 @@ size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) { packOptions.resolution = graph.metadata["baking"]["resolution"].as(packOptions.resolution); // pack +#if UF_XATLAS_UNWRAP_SERIAL + size_t atlasCount = 0; + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); + + for ( auto& entry : atlas.entries ) { + ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); + if (error != ::xatlas::AddMeshError::Success) { + ::xatlas::Destroy(atlas.pointer); + UF_EXCEPTION("{}", ::xatlas::StringForEnum(error)); + } + } + + ::xatlas::Generate(atlas.pointer, chartOptions, packOptions); + + for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { + auto& xmesh = atlas.pointer->meshes[i]; + auto& entry = atlas.entries[i]; + auto& name = graph.meshes[entry.index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + + // draw commands + if ( mesh.indirect.count ) { + auto vertexInput = mesh.remapVertexInput( entry.commandID ); + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto k = 0; k < vertexInput.attributes.size(); ++k ) { + auto dstAttribute = vertexInput.attributes[k]; + if ( dstAttribute.descriptor.name != "st" ) continue; + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + vertexInput.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; + } + } + } else { + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { + auto dstAttribute = mesh.vertex.attributes[k]; + if ( dstAttribute.descriptor.name != "st" ) continue; + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (ref + mesh.vertex.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };; + } + } + } + mesh.updateDescriptor(); + } + + ::xatlas::Destroy(atlas.pointer); + ++atlasCount; + } +#else + // add mesh decls to mesh atlases + // done after the fact since we'll know the total amount of meshes added + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); + + for ( auto& entry : atlas.entries ) { + ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); + if (error != ::xatlas::AddMeshError::Success) { + ::xatlas::Destroy(atlas.pointer); + UF_EXCEPTION("{}", ::xatlas::StringForEnum(error)); + } + } + } + #if UF_XATLAS_UNWRAP_MULTITHREAD auto tasks = uf::thread::schedule(true); #else @@ -577,6 +647,7 @@ size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) { ::xatlas::Destroy(atlas.pointer); ++atlasCount; } +#endif return atlasCount; } #endif \ No newline at end of file diff --git a/engine/src/utils/math/physics.cpp b/engine/src/utils/math/physics.cpp index 6f240069..90ca3d5e 100644 --- a/engine/src/utils/math/physics.cpp +++ b/engine/src/utils/math/physics.cpp @@ -1,11 +1,13 @@ #include #include +/* uf::Timer<> uf::physics::time::timer; double uf::physics::time::current = 0; double uf::physics::time::previous = 0; float uf::physics::time::delta = 0; float uf::physics::time::clamp = 0; +*/ void UF_API uf::physics::initialize() { diff --git a/engine/src/utils/serialize/serializer.cpp b/engine/src/utils/serialize/serializer.cpp index e42d6663..c1fef46a 100644 --- a/engine/src/utils/serialize/serializer.cpp +++ b/engine/src/utils/serialize/serializer.cpp @@ -67,7 +67,7 @@ bool uf::Serializer::readFromFile( const uf::stl::string& filename, const uf::st #if UF_SERIALIZER_IMPLICIT_LOAD // implicitly check for optimal format for plain .json requests if ( uf::string::matched( filename, "/\\.json$/" ) ) { - #if UF_USE_TOML + #if 0 && UF_USE_TOML uf::stl::string toml_filename = uf::string::replace( filename, "/\\.json$/", ".toml" ); // load from toml if newer if ( uf::io::mtime( toml_filename ) > uf::io::mtime( filename ) ) { UF_MSG_DEBUG("Deserialize redirect: {} -> {}", filename, toml_filename); @@ -102,6 +102,7 @@ bool uf::Serializer::readFromFile( const uf::stl::string& filename, const uf::st this->deserialize( buffer, settings ); #if UF_SERIALIZER_AUTO_CONVERT +#if 0 && UF_USE_TOML if ( uf::string::matched( filename, "/\\.json$/" ) ) { if ( ext::json::PREFERRED_ENCODING != "toml" ) { uf::stl::string _filename = uf::string::replace( filename, "/\\.json$/", ".toml" ); @@ -117,6 +118,7 @@ bool uf::Serializer::readFromFile( const uf::stl::string& filename, const uf::st } } } +#endif if ( uf::string::matched( filename, "/\\.(json|toml)$/" ) ) { // auto convert read JSON file to TOML diff --git a/engine/src/utils/time/time.cpp b/engine/src/utils/time/time.cpp index a868456c..7789354a 100644 --- a/engine/src/utils/time/time.cpp +++ b/engine/src/utils/time/time.cpp @@ -3,4 +3,10 @@ namespace { uf::Time<> zero = spec::time.getTime(); // Program epoch, used for getting time deltas (without uf::Timer) } -extern UF_API uf::Timer<> timer; // System timer, used for getting time deltas \ No newline at end of file +extern UF_API uf::Timer<> timer; // System timer, used for getting time deltas + +uf::Timer<> uf::time::timer; +double uf::time::current = 0; +double uf::time::previous = 0; +float uf::time::delta = 0; +float uf::time::clamp = 0; \ No newline at end of file diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 09cfba73..fb439cc5 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -37,7 +37,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { sceneMetadata.shadow.update = metadata.max.shadows; UF_MSG_DEBUG("Temporarily altering shadow limits..."); - this->addHook( "entity:PostInitialization.%UID%", [&]( ext::json::Value& ){ + this->addHook( "entity:PostInitialization.%UID%", [&](){ metadata.output = this->resolveURI( metadataJson["baking"]["output"].as(), metadataJson["baking"]["root"].as() ); metadata.renderModeName = "B:" + std::to_string((int) this->getUid()); @@ -94,7 +94,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { UF_MSG_DEBUG("Finished initialiation."); }); - this->queueHook( "entity:PostInitialization.%UID%", ext::json::null(), 1 ); + this->queueHook( "entity:PostInitialization.%UID%", 1.0f ); #endif } void ext::BakingBehavior::tick( uf::Object& self ) { @@ -104,7 +104,7 @@ void ext::BakingBehavior::tick( uf::Object& self ) { auto& renderMode = this->getComponent(); if ( renderMode.executed && !metadata.initialized.renderMode ) goto PREPARE; else if ( renderMode.executed && !metadata.initialized.map ) { - TIMER(1.0, (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) && ) { + TIMER(1.0, (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) ) { goto SAVE; } } diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 9be12391..23970a38 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -50,6 +50,9 @@ void ext::LightBehavior::initialize( uf::Object& self ) { metadataJson["light"]["color"][1] = 1; //metadataJson["light"]["color"]["random"].as() ? (rand() % 100) / 100.0 : 1; metadataJson["light"]["color"][2] = 1; //metadataJson["light"]["color"]["random"].as() ? (rand() % 100) / 100.0 : 1; } + if ( metadataJson["light"]["type"].as() == "point" ) { + transform.orientation = uf::quaternion::identity(); + } #if UF_USE_OPENGL metadataJson["light"]["shadows"] = false; #endif @@ -244,6 +247,7 @@ void ext::LightBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer["light"]["power"] = /*this->*/power; serializer["light"]["bias"]["shader"] = /*this->*/bias; serializer["light"]["shadows"] = /*this->*/shadows; + serializer["light"]["global"] = /*this->*/global; serializer["system"]["renderer"]["mode"] = /*this->*/renderer.mode; serializer["light"]["external update"] = /*this->*/renderer.external; // serializer["system"]["renderer"]["timer"] = /*this->*/renderer.limiter; @@ -258,6 +262,7 @@ void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer /*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); diff --git a/ext/behaviors/light/behavior.h b/ext/behaviors/light/behavior.h index 587baae9..ddb6e6af 100644 --- a/ext/behaviors/light/behavior.h +++ b/ext/behaviors/light/behavior.h @@ -17,6 +17,7 @@ namespace ext { float bias = 0.0f; bool shadows = false; int32_t type = 1; + bool global = false; struct { uf::stl::string mode = "in-range"; float limiter = 0.0f; diff --git a/ext/behaviors/player/behavior.cpp b/ext/behaviors/player/behavior.cpp index 8fbd7761..7e0f4bbb 100644 --- a/ext/behaviors/player/behavior.cpp +++ b/ext/behaviors/player/behavior.cpp @@ -41,7 +41,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) { cameraTransform.scale = uf::vector::decode( metadataJson["camera"]["scale"], cameraTransform.scale ); cameraTransform.reference = &transform; - auto& cameraSettingsJson = metadataJson["camera"]["settings"]; + auto cameraSettingsJson = metadataJson["camera"]["settings"]; if ( metadataJson["camera"]["ortho"].as() ) { float l = cameraSettingsJson["left"].as(); @@ -215,7 +215,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { } } #if 0 - TIMER(0.25, keys.use && ) { + TIMER(0.25, keys.use ) { size_t uid = 0; float depth = -1; uf::Object* pointer = NULL; @@ -331,7 +331,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { if ( metadata.system.control ) { // noclip handler - TIMER(0.25, keys.vee && ) { + TIMER(0.25, keys.vee ) { bool state = !stats.noclipped; metadata.system.noclipped = state; if ( collider.body ) { @@ -365,9 +365,14 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { } if ( !stats.floored ) stats.walking = false; } + TIMER(0.0625, stats.floored && keys.jump ) { + physics.linear.velocity += translator.up * metadata.movement.jump; + } +/* if ( stats.floored && keys.jump ) { physics.linear.velocity += translator.up * metadata.movement.jump; } +*/ if ( keys.crouch ) { if ( stats.noclipped ) physics.linear.velocity -= translator.up * metadata.movement.jump; else { diff --git a/ext/behaviors/raytrace/behavior.cpp b/ext/behaviors/raytrace/behavior.cpp index 9cfc7cd0..bb5c9a45 100644 --- a/ext/behaviors/raytrace/behavior.cpp +++ b/ext/behaviors/raytrace/behavior.cpp @@ -28,7 +28,10 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) { renderMode->setTarget("Compute"); renderMode->metadata.json["shaders"]["vertex"] = "/shaders/display/renderTargetSimple.vert.spv"; renderMode->metadata.json["shaders"]["fragment"] = "/shaders/display/renderTargetSimple.frag.spv"; - renderMode->blitter.descriptor.subpass = 1; + + renderMode->blitter.descriptor.renderMode = "Swapchain"; + renderMode->blitter.descriptor.subpass = 0; + renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt; renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt); renderMode->execute = false; @@ -202,7 +205,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) { } } - TIMER(1.0, uf::Window::isKeyPressed("R") && ) { + TIMER(1.0, uf::Window::isKeyPressed("R") ) { UF_MSG_DEBUG("Screenshotting RT scene..."); image.screenshot().save("./data/rt.png"); } diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 04b6e375..0e358b6d 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -65,7 +65,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) { }); this->addHook( "menu:Open", [&](pod::payloads::menuOpen& payload){ - TIMER(1, true && ) { + TIMER(1) { uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager"); if ( !manager ) return; @@ -222,7 +222,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } /* Print World Tree */ { - TIMER(1, uf::inputs::kbm::states::U && ) { + TIMER(1, uf::inputs::kbm::states::U ) { std::function filter = []( uf::Entity* entity, int indent ) { for ( int i = 0; i < indent; ++i ) uf::iostream << "\t"; uf::iostream << uf::string::toString(entity->as()) << " "; @@ -240,7 +240,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } } /* Mark as ready for multithreading */ { - TIMER(1, uf::inputs::kbm::states::M && ) { + TIMER(1, uf::inputs::kbm::states::M ) { uf::renderer::settings::experimental::dedicatedThread = !uf::renderer::settings::experimental::dedicatedThread; UF_MSG_DEBUG("Toggling multithreaded rendering..."); } @@ -248,7 +248,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { #endif #if 0 /* Print World Tree */ { - TIMER(1, uf::inputs::kbm::states::U && false && ) { + TIMER(1, uf::inputs::kbm::states::U ) { std::function filter = []( uf::Entity* entity, int indent ) { for ( int i = 0; i < indent; ++i ) uf::iostream << "\t"; uf::iostream << uf::string::toString(entity->as()) << " ["; @@ -351,6 +351,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { pod::Vector4f color = {0,0,0,1}; // OpenGL requires an alpha float distance = 0; float power = 0; + bool global = 0; }; uf::stl::vector entities; for ( auto entity : graph ) { @@ -364,11 +365,14 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { .color = metadata.color, .distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ), .power = metadata.power, + .global = metadata.global, }); info.position.w = 1; info.color.w = 1; } std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){ + if ( l.global && !r.global ) return true; + if ( !l.global && r.global ) return false; return l.distance < r.distance; }); @@ -416,6 +420,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { float bias = 0; int32_t type = 0; bool shadows = false; + bool global = false; }; uf::stl::vector entities; entities.reserve(graph.size() / 2); @@ -450,10 +455,13 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { .bias = metadata.bias, .type = metadata.type, .shadows = metadata.shadows && hasRT, + .global = metadata.global, }); } // prioritize closer lights; it would be nice to also prioritize lights in view, but because of VXGI it's not really something to do std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){ + if ( l.global && !r.global ) return true; + if ( !l.global && r.global ) return false; return l.distance < r.distance; }); diff --git a/ext/behaviors/scene/behavior.h b/ext/behaviors/scene/behavior.h index 7fb5a688..34b4cca2 100644 --- a/ext/behaviors/scene/behavior.h +++ b/ext/behaviors/scene/behavior.h @@ -73,7 +73,7 @@ namespace ext { } sky; ); - void bindBuffers( uf::Object&, const uf::stl::string& = "", const uf::stl::string& = "fragment", const uf::stl::string& = "" ); - void bindBuffers( uf::Object&, uf::renderer::Graphic&, const uf::stl::string& = "fragment", const uf::stl::string& = "" ); + void bindBuffers( uf::Object&, const uf::stl::string& = "", const uf::stl::string& = "fragment", const uf::stl::string& = "deferred" ); + void bindBuffers( uf::Object&, uf::renderer::Graphic&, const uf::stl::string& = "fragment", const uf::stl::string& = "deferred" ); } } \ No newline at end of file diff --git a/ext/behaviors/voxelizer/behavior.cpp b/ext/behaviors/voxelizer/behavior.cpp index 175d0e8b..d58ef0af 100644 --- a/ext/behaviors/voxelizer/behavior.cpp +++ b/ext/behaviors/voxelizer/behavior.cpp @@ -434,7 +434,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) { } #endif } - ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute" ); + ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute", "" ); ext::ExtSceneBehavior::bindBuffers( scene ); #endif } diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index 2666161e..d2d621de 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -54,7 +54,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) { if ( !uf::renderer::hasRenderMode( "Gui", true ) ) { auto& renderMode = this->getComponent(); uf::stl::string name = "Gui"; - renderMode.blitter.descriptor.subpass = 1; + renderMode.blitter.descriptor.subpass = 0; renderMode.metadata.type = "single"; uf::renderer::addRenderMode( &renderMode, name ); } @@ -99,6 +99,8 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) { if ( !blitter.initialized ) return; if ( !blitter.material.hasShader("fragment") ) return; + + return; auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); diff --git a/ext/main.cpp b/ext/main.cpp index c88c4eb4..0a6f3c7a 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -200,18 +200,18 @@ void EXT_API ext::initialize() { uf::allocator::override = configMemoryPoolJson["override"].as( uf::allocator::override ); } /* Ext config */ { - ::config.engine.gc.every = ::json["engine"]["debug"]["garbage collection"]["every"].as(); - ::config.engine.gc.mode = ::json["engine"]["debug"]["garbage collection"]["mode"].as(); - ::config.engine.gc.announce = ::json["engine"]["debug"]["garbage collection"]["announce"].as(); + ::config.engine.gc.every = ::json["engine"]["debug"]["garbage collection"]["every"].as(::config.engine.gc.every); + ::config.engine.gc.mode = ::json["engine"]["debug"]["garbage collection"]["mode"].as(::config.engine.gc.mode); + ::config.engine.gc.announce = ::json["engine"]["debug"]["garbage collection"]["announce"].as(::config.engine.gc.announce); - ::config.engine.ext.ultralight.enabled = ::json["engine"]["ext"]["ultralight"]["enabled"].as(); - ::config.engine.ext.discord.enabled = ::json["engine"]["ext"]["discord"]["enabled"].as(); - ::config.engine.ext.imgui.enabled = ::json["engine"]["ext"]["imgui"]["enabled"].as(); + ::config.engine.ext.ultralight.enabled = ::json["engine"]["ext"]["ultralight"]["enabled"].as(::config.engine.ext.ultralight.enabled); + ::config.engine.ext.discord.enabled = ::json["engine"]["ext"]["discord"]["enabled"].as(::config.engine.ext.discord.enabled); + ::config.engine.ext.imgui.enabled = ::json["engine"]["ext"]["imgui"]["enabled"].as(::config.engine.ext.imgui.enabled); - ::config.engine.limiter.print = ::json["engine"]["debug"]["framerate"]["print"].as(); + ::config.engine.limiter.print = ::json["engine"]["debug"]["framerate"]["print"].as(::config.engine.limiter.print); - ::config.engine.fps.print = ::json["engine"]["debug"]["framerate"]["print"].as(); - ::config.engine.fps.every = ::json["engine"]["debug"]["framerate"]["every"].as(); + ::config.engine.fps.print = ::json["engine"]["debug"]["framerate"]["print"].as(::config.engine.fps.print); + ::config.engine.fps.every = ::json["engine"]["debug"]["framerate"]["every"].as(::config.engine.fps.every); } { uf::Mesh::defaultInterleaved = ::json["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved ); @@ -220,6 +220,8 @@ void EXT_API ext::initialize() { #else uf::matrix::reverseInfiniteProjection = ::json["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection ); #endif + + uf::graph::initialBufferElements = ::json["engine"]["graph"]["initial buffer elements"].as(uf::graph::initialBufferElements); } /* Create initial scene (kludge) */ { @@ -367,8 +369,8 @@ void EXT_API ext::initialize() { uf::renderer::settings::width *= scale; uf::renderer::settings::height *= scale; } else if ( ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) { - uf::renderer::settings::width = configRenderJson["framebuffer"]["size"][0].as(); - uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as(); + uf::renderer::settings::width = configRenderJson["framebuffer"]["size"][0].as(uf::renderer::settings::width); + uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as(uf::renderer::settings::height); uf::stl::string filter = uf::string::lowercase( configRenderJson["framebuffer"]["size"][2].as() ); if ( filter == "nearest" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::NEAREST; @@ -419,6 +421,7 @@ void EXT_API ext::initialize() { uf::renderer::settings::invariant::deferredAliasOutputToSwapchain = configRenderInvariantJson["deferred alias output to swapchain"].as( uf::renderer::settings::invariant::deferredAliasOutputToSwapchain ); uf::renderer::settings::invariant::deferredSampling = configRenderInvariantJson["deferred sampling"].as( uf::renderer::settings::invariant::deferredSampling ); + uf::renderer::settings::pipelines::deferred = configRenderPipelinesJson["deferred"].as( uf::renderer::settings::pipelines::deferred ); uf::renderer::settings::pipelines::vsync = configRenderPipelinesJson["vsync"].as( uf::renderer::settings::pipelines::vsync ); uf::renderer::settings::pipelines::hdr = configRenderPipelinesJson["hdr"].as( uf::renderer::settings::pipelines::hdr ); uf::renderer::settings::pipelines::vxgi = configRenderPipelinesJson["vxgi"].as( uf::renderer::settings::pipelines::vxgi ); @@ -479,7 +482,7 @@ void EXT_API ext::initialize() { } else if ( configVrJson["dominant eye"].as() == "left" ) ext::openvr::dominantEye = 0; else if ( configVrJson["dominant eye"].as() == "right" ) ext::openvr::dominantEye = 1; - ext::openvr::driver.manifest = configVrJson["manifest"].as(); + ext::openvr::driver.manifest = configVrJson["manifest"].as(ext::openvr::driver.manifest); if ( ext::openvr::enabled ) ::json["engine"]["render modes"]["stereo deferred"] = true; } @@ -489,19 +492,29 @@ void EXT_API ext::initialize() { // setup render mode if ( ::json["engine"]["render modes"]["gui"].as(true) ) { auto* renderMode = new uf::renderer::RenderTargetRenderMode; - renderMode->blitter.descriptor.subpass = 1; + renderMode->blitter.descriptor.renderMode = "Swapchain"; + renderMode->blitter.descriptor.subpass = 0; renderMode->metadata.type = "single"; uf::renderer::addRenderMode( renderMode, "Gui" ); } - if ( ::json["engine"]["render modes"]["deferred"].as(true) ) { - uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" ); - auto& renderMode = uf::renderer::getRenderMode("Deferred", true); + if ( uf::renderer::settings::pipelines::deferred ) { + auto* renderMode = new uf::renderer::DeferredRenderMode; + + renderMode->blitter.descriptor.renderMode = "Swapchain"; + renderMode->blitter.descriptor.subpass = 0; + if ( ::json["engine"]["render modes"]["stereo deferred"].as() ) { - renderMode.metadata.eyes = 2; + renderMode->metadata.eyes = 2; + } + + if ( uf::renderer::settings::pipelines::deferred ) { + renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::deferred); } if ( uf::renderer::settings::pipelines::culling ) { - renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling); + renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::culling); } + + uf::renderer::addRenderMode( renderMode, "" ); } #if UF_USE_VULKAN @@ -683,7 +696,7 @@ void EXT_API ext::tick() { } #endif /* Print Memory Pool Information */ { - TIMER(1, uf::inputs::kbm::states::P && ) { + TIMER(1, uf::inputs::kbm::states::P ) { // uf::iostream << uf::renderer::allocatorStats() << "\n"; UF_MSG_DEBUG("==== Memory Pool Information ===="); if ( uf::memoryPool::global.size() > 0 ) UF_MSG_DEBUG("Global Memory Pool: {}", uf::memoryPool::global.stats()); @@ -694,12 +707,12 @@ void EXT_API ext::tick() { } #if 0 /* Attempt to reset VR position */ { - TIMER(1, uf::inputs::kbm::states::Z && ) { + TIMER(1, uf::inputs::kbm::states::Z ) { uf::hooks.call("VR:Seat.Reset"); } } /* Print controller position */ if ( false ) { - TIMER(1, uf::inputs::kbm::states::Z && ) { + TIMER(1, uf::inputs::kbm::states::Z ) { auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); auto& camera = controller.getComponent();