Commit for 2022.07.16 23-28-12.7z
This commit is contained in:
parent
e71f76421c
commit
60e64ccb0d
@ -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,
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
{
|
||||
"assets": ["./scripts/door.lua"],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"metadata": {
|
||||
"physics": {
|
||||
"mass": 0,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 ]
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
{
|
||||
"assets": [],
|
||||
"behaviors": [
|
||||
"SoundEmitterBehavior"
|
||||
],
|
||||
"metadata": {
|
||||
"holdable": true,
|
||||
"physics": {
|
||||
|
||||
@ -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 )
|
||||
|
||||
@ -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
|
||||
} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@
|
||||
"import": "/player.json",
|
||||
"assets": [
|
||||
// { "filename": "/gui/hud/hud.json", "delay": 0 }
|
||||
],
|
||||
"metadata": {
|
||||
}
|
||||
]
|
||||
// "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } }
|
||||
}
|
||||
@ -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 ],
|
||||
|
||||
34
bin/data/scenes/construct/sound.json
Normal file
34
bin/data/scenes/construct/sound.json
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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] } },
|
||||
|
||||
@ -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" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
@ -100,6 +100,7 @@ namespace pod {
|
||||
|
||||
namespace uf {
|
||||
namespace graph {
|
||||
extern UF_API size_t initialBufferElements;
|
||||
extern UF_API pod::Graph::Storage storage;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,9 @@ namespace uf {
|
||||
template<typename T> 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<typename T>
|
||||
void queueHook( const uf::stl::string&, const T&, float = 0 );
|
||||
|
||||
@ -36,13 +36,13 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const T&
|
||||
|
||||
template<typename T>
|
||||
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<uf::ObjectBehavior::Metadata>();
|
||||
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<T>(p);
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <nlohmann/fifo_map.hpp>
|
||||
|
||||
#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<class K, class V, class dummy_compare, class A>
|
||||
using fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
|
||||
typedef nlohmann::basic_json<fifo_map> base_value;
|
||||
#else
|
||||
typedef nlohmann::ordered_json base_value;
|
||||
#endif
|
||||
#if UF_JSON_NLOHMANN_FIFO_MAP
|
||||
template<class K, class V, class dummy_compare, class A>
|
||||
using fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
|
||||
typedef nlohmann::basic_json<fifo_map> 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<uf::stl::string>(bool strict) const
|
||||
template<> inline bool ext::json::Value::is<unsigned int>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
|
||||
#endif
|
||||
template<typename T> inline T ext::json::Value::as() const {
|
||||
return !is<T>() ? T() : get<T>();
|
||||
return !is<T>(false) ? T() : get<T>();
|
||||
/*
|
||||
if ( !is<T>() ) return T();
|
||||
return get<T>();
|
||||
*/
|
||||
}
|
||||
template<typename T> inline T ext::json::Value::as( const T& fallback ) const {
|
||||
return !is<T>() ? fallback : get<T>();
|
||||
return !is<T>(false) ? fallback : get<T>();
|
||||
/*
|
||||
if ( !is<T>() ) return fallback;
|
||||
return get<T>();
|
||||
|
||||
@ -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<std::mutex> guardMutex( std::thread::id = std::this_thread::get_id() );
|
||||
|
||||
void cleanupAllCommands();
|
||||
void cleanupCommands( std::thread::id = std::this_thread::get_id() );
|
||||
|
||||
virtual ~RenderMode();
|
||||
|
||||
@ -12,6 +12,7 @@ namespace ext {
|
||||
|
||||
virtual void initialize( Device& device );
|
||||
virtual void createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics );
|
||||
virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 );
|
||||
virtual void tick();
|
||||
virtual void render();
|
||||
virtual void destroy();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<long long> timer(false);\
|
||||
if ( !timer.running() ) timer.start(uf::Time<long long>(-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<long long> timer(false);\
|
||||
if ( !timer.running() ) timer.start(uf::Time<long long>(-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;\
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -81,6 +81,14 @@ namespace uf {
|
||||
const uf::Time<T>& getStarting() const;
|
||||
const uf::Time<T>& 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"
|
||||
|
||||
@ -64,7 +64,7 @@ void uf::Asset::processQueue() {
|
||||
auto jobs = std::move(this->getComponent<Job::container_t>());
|
||||
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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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...");
|
||||
|
||||
@ -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<bool>(true) ) {
|
||||
|
||||
@ -10,16 +10,27 @@
|
||||
#include <uf/utils/memory/map.h>
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
|
||||
#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<uf::stl::string, bool> isSrgb;
|
||||
|
||||
// process lightmap
|
||||
|
||||
UF_DEBUG_TIMER_MULTITRACE("Parsing lightmaps");
|
||||
{
|
||||
constexpr const char* UF_GRAPH_DEFAULT_LIGHTMAP = "./lightmap.%i.png";
|
||||
uf::stl::unordered_map<size_t, uf::stl::string> 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<bool>() ) for ( auto& name : graph.materials ) UF_MSG_DEBUG("Material: {}", name);
|
||||
if ( graph.metadata["debug"]["print"]["textures"].as<bool>() ) 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<bool>()) ) {
|
||||
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<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) if ( graph.lights.count(node.name) > 0 ) return;
|
||||
|
||||
|
||||
// create child if requested
|
||||
if ( graph.metadata["lights"]["lightmapped"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(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<bool>(false) && !tag["bake"].as<bool>(true) ) ignore = true;
|
||||
if ( tag["ignore"].as<bool>() ) 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<uf::Serializer>();
|
||||
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<bool>() ) return;
|
||||
if ( graph.metadata["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(true) ) return;
|
||||
|
||||
if ( ext::json::isObject( tag ) ) {
|
||||
if ( tag["action"].as<uf::stl::string>() == "load" ) {
|
||||
if ( tag["filename"].is<uf::stl::string>() ) {
|
||||
uf::stl::string filename = uf::io::resolveURI( tag["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
@ -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<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
|
||||
auto& child = entity.loadChild( filename, false );
|
||||
auto& childTransform = child.getComponent<pod::Transform<>>();
|
||||
auto& childMetadataJson = child.getComponent<uf::Serializer>();
|
||||
|
||||
auto flatten = uf::transform::flatten( node.transform );
|
||||
if ( !tag["preserve position"].as<bool>() ) childTransform.position = flatten.position;
|
||||
if ( !tag["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
|
||||
// childTransform.position = flatten.position;
|
||||
// childTransform.orientation = flatten.orientation;
|
||||
// childMetadataJson["transform"] = uf::transform::encode( flatten );
|
||||
}
|
||||
if ( tag["static"].is<bool>() ) {
|
||||
metadata.system.ignoreGraph = tag["static"].as<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
// 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<bool>();
|
||||
|
||||
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<uf::stl::string>() == "point" ) {
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
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<pod::Transform<>>();
|
||||
@ -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<pod::Transform<>>();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
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<bool>()) ) 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<pod::Instance> 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<pod::Instance::Addresses> 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<pod::Instance::Addresses> 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<pod::Matrix4f> 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<uf::Camera>();
|
||||
|
||||
#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<pod::Transform<>>() ));
|
||||
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();
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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<uf::ObjectBehavior::Metadata>();
|
||||
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<uf::ObjectBehavior::Metadata>();
|
||||
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;
|
||||
|
||||
@ -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<pod::Transform<>>();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
|
||||
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 ) {
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<bool>(true)) ){
|
||||
if ( graph.metadata["renderer"]["invert"].as<bool>(true) ){
|
||||
vertex.position.x = -vertex.position.x;
|
||||
vertex.normal.x = -vertex.normal.x;
|
||||
#if UF_GRAPH_PROCESS_PRIMITIVES_FULL
|
||||
|
||||
@ -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 );
|
||||
}
|
||||
|
||||
@ -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 ) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<std::mutex> 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<uint32_t>(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
|
||||
@ -21,21 +21,51 @@ const uf::stl::string ext::vulkan::BaseRenderMode::getType() const {
|
||||
return "Swapchain";
|
||||
}
|
||||
void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& 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<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"RenderTarget", "Compute", "Deferred"}, false);
|
||||
if ( !settings::pipelines::rt ) {
|
||||
std::reverse( layers.begin(), layers.end() );
|
||||
}
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
auto& commands = getCommands();
|
||||
|
||||
uf::stl::vector<VkClearValue> 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::vector<ex
|
||||
renderPassBeginInfo.renderArea.offset.y = 0;
|
||||
renderPassBeginInfo.renderArea.extent.width = width;
|
||||
renderPassBeginInfo.renderArea.extent.height = height;
|
||||
renderPassBeginInfo.clearValueCount = 2;
|
||||
renderPassBeginInfo.pClearValues = clearValues;
|
||||
auto& commands = getCommands();
|
||||
renderPassBeginInfo.clearValueCount = clearValues.size();
|
||||
renderPassBeginInfo.pClearValues = &clearValues[0];
|
||||
|
||||
// Update dynamic viewport state
|
||||
VkViewport viewport = {};
|
||||
viewport.width = (float) width;
|
||||
viewport.height = (float) height;
|
||||
viewport.minDepth = (float) 0.0f;
|
||||
viewport.maxDepth = (float) 1.0f;
|
||||
|
||||
// Update dynamic scissor state
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.width = width;
|
||||
scissor.extent.height = height;
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
|
||||
for (size_t i = 0; i < commands.size(); ++i) {
|
||||
// Set target frame buffer
|
||||
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];
|
||||
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
|
||||
// Fill GBuffer
|
||||
{
|
||||
size_t currentSubpass = 0;
|
||||
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &commandBufferInfo));
|
||||
{
|
||||
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;
|
||||
|
||||
// Start the first sub pass specified in our default render pass setup by the base class
|
||||
// This will clear the color and depth attachment
|
||||
vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
// Update dynamic viewport state
|
||||
VkViewport viewport = {};
|
||||
viewport.height = (float) height;
|
||||
viewport.width = (float) width;
|
||||
viewport.minDepth = (float) 0.0f;
|
||||
viewport.maxDepth = (float) 1.0f;
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
// Update dynamic scissor state
|
||||
VkRect2D scissor = {};
|
||||
scissor.extent.width = width;
|
||||
scissor.extent.height = height;
|
||||
scissor.offset.x = 0;
|
||||
scissor.offset.y = 0;
|
||||
vkCmdSetScissor(commands[i], 0, 1, &scissor);
|
||||
// explicitly transfer queue-ownership
|
||||
if ( ext::vulkan::device.queueFamilyIndices.graphics != ext::vulkan::device.queueFamilyIndices.present ) {
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.present;
|
||||
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics;
|
||||
} else {
|
||||
imageMemoryBarrier.srcQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.present;
|
||||
imageMemoryBarrier.dstQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.graphics;
|
||||
}
|
||||
imageMemoryBarrier.image = renderTarget.attachments[i].image;
|
||||
// imageMemoryBarrier.subresourceRange = subResourceRange;
|
||||
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;
|
||||
|
||||
for ( auto graphic : graphics ) {
|
||||
graphic->record(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
|
||||
@ -35,14 +35,15 @@ uf::stl::vector<ext::vulkan::Graphic*> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<uf::Serializer>();
|
||||
|
||||
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<bool, uf::stl::string> 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<bool, uf::stl::string> 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<uf::Serializer>();
|
||||
{
|
||||
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<bool, uf::stl::string> 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<size_t>(512);
|
||||
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(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<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"RenderTarget", "Compute"}, false);
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadata = scene.getComponent<uf::Serializer>();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
|
||||
auto& commands = getCommands();
|
||||
auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
|
||||
// auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
|
||||
uf::stl::vector<VkClearValue> 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<VkClearValue> 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<float>(),
|
||||
v[1].as<float>(),
|
||||
v[2].as<float>(),
|
||||
v[3].as<float>(),
|
||||
} };
|
||||
} 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]));
|
||||
|
||||
@ -35,7 +35,15 @@ uf::stl::vector<ext::vulkan::Graphic*> 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<bool, uf::stl::string> 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<ext::vulkan::Graphic*>& 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::Serializer>();
|
||||
|
||||
uf::stl::vector<VkClearValue> 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<VkClearValue> 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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() );
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include <xatlas/xatlas.h>
|
||||
|
||||
#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<bool>(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<uf::Mesh> sources;
|
||||
sources.reserve(graph.meshes.size());
|
||||
uf::stl::vector<uf::Mesh> sources(graph.meshes.size());
|
||||
|
||||
uf::stl::unordered_map<size_t, Atlas> 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<bool>(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<bool>(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<bool>(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<bool>(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<uint8_t*>(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<uint8_t*>(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
|
||||
@ -1,11 +1,13 @@
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <iostream>
|
||||
|
||||
/*
|
||||
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() {
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
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;
|
||||
@ -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<uf::stl::string>(), metadataJson["baking"]["root"].as<uf::stl::string>() );
|
||||
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<uf::renderer::RenderTargetRenderMode>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,9 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
metadataJson["light"]["color"][1] = 1; //metadataJson["light"]["color"]["random"].as<bool>() ? (rand() % 100) / 100.0 : 1;
|
||||
metadataJson["light"]["color"][2] = 1; //metadataJson["light"]["color"]["random"].as<bool>() ? (rand() % 100) / 100.0 : 1;
|
||||
}
|
||||
if ( metadataJson["light"]["type"].as<uf::stl::string>() == "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<float>(/*this->*/power);
|
||||
/*this->*/bias = serializer["light"]["bias"]["shader"].as<float>(/*this->*/bias);
|
||||
/*this->*/shadows = serializer["light"]["shadows"].as<bool>(/*this->*/shadows);
|
||||
/*this->*/global = serializer["light"]["global"].as<bool>(/*this->*/global);
|
||||
/*this->*/renderer.mode = serializer["system"]["renderer"]["mode"].as<uf::stl::string>(/*this->*/renderer.mode);
|
||||
// /*this->*/renderer.rendered = false;
|
||||
/*this->*/renderer.external = serializer["light"]["external update"].as<bool>(/*this->*/renderer.external);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<bool>() ) {
|
||||
float l = cameraSettingsJson["left"].as<float>();
|
||||
@ -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 {
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
|
||||
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
|
||||
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " ";
|
||||
@ -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<void(uf::Entity*, int)> filter = []( uf::Entity* entity, int indent ) {
|
||||
for ( int i = 0; i < indent; ++i ) uf::iostream << "\t";
|
||||
uf::iostream << uf::string::toString(entity->as<uf::Object>()) << " [";
|
||||
@ -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<LightInfo> 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<LightInfo> 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;
|
||||
});
|
||||
|
||||
|
||||
@ -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" );
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
if ( !uf::renderer::hasRenderMode( "Gui", true ) ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
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();
|
||||
|
||||
55
ext/main.cpp
55
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<float>();
|
||||
::config.engine.gc.mode = ::json["engine"]["debug"]["garbage collection"]["mode"].as<uint64_t>();
|
||||
::config.engine.gc.announce = ::json["engine"]["debug"]["garbage collection"]["announce"].as<bool>();
|
||||
::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<bool>();
|
||||
::config.engine.ext.discord.enabled = ::json["engine"]["ext"]["discord"]["enabled"].as<bool>();
|
||||
::config.engine.ext.imgui.enabled = ::json["engine"]["ext"]["imgui"]["enabled"].as<bool>();
|
||||
::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<bool>();
|
||||
::config.engine.limiter.print = ::json["engine"]["debug"]["framerate"]["print"].as(::config.engine.limiter.print);
|
||||
|
||||
::config.engine.fps.print = ::json["engine"]["debug"]["framerate"]["print"].as<bool>();
|
||||
::config.engine.fps.every = ::json["engine"]["debug"]["framerate"]["every"].as<float>();
|
||||
::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<float>();
|
||||
uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as<float>();
|
||||
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<uf::stl::string>() );
|
||||
|
||||
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<uf::stl::string>() == "left" ) ext::openvr::dominantEye = 0;
|
||||
else if ( configVrJson["dominant eye"].as<uf::stl::string>() == "right" ) ext::openvr::dominantEye = 1;
|
||||
|
||||
ext::openvr::driver.manifest = configVrJson["manifest"].as<uf::stl::string>();
|
||||
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<bool>(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<bool>(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<bool>() ) {
|
||||
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<uf::Camera>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user