Commit for 2022.07.13 22-34-59.7z

This commit is contained in:
mrq 2022-07-13 22:34:00 -05:00
parent 403aa11343
commit 14e7a9aa6d
38 changed files with 872 additions and 239 deletions

View File

@ -58,9 +58,9 @@ DEPS +=
ifneq (,$(findstring win64,$(ARCH)))
ifneq (,$(findstring zig,$(CC)))
REQ_DEPS += $(RENDERER) json:nlohmann png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux
REQ_DEPS += $(RENDERER) json:nlohmann toml png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux
else
REQ_DEPS += $(RENDERER) json:nlohmann png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux
REQ_DEPS += $(RENDERER) json:nlohmann toml png zlib luajit reactphysics meshoptimizer xatlas simd ctti gltf imgui fmt curl freetype openal ogg # ncurses openvr draco discord bullet ultralight-ux
endif
FLAGS += -DUF_ENV_WINDOWS -DUF_ENV_WIN64 -DWIN32_LEAN_AND_MEAN
DEPS += -lgdi32 -ldwmapi
@ -224,6 +224,9 @@ ifneq (,$(findstring ctti,$(REQ_DEPS)))
else
FLAGS += -DUF_RTTI -rtti
endif
ifneq (,$(findstring toml,$(REQ_DEPS)))
FLAGS += -DUF_USE_TOML
endif
# SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp)
#SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp)

View File

@ -40,7 +40,7 @@
"rt": {
// "size": [ 1280, 720 ],
"filter": "nearest",
"defaultRayBounds": [ 0.001, 1024.0 ],
"defaultRayBounds": [ 0.0001, 256.0 ],
"alphaTestOffset": 0.001,
"samples": 1,
"paths": 2,
@ -186,7 +186,7 @@
"compression": "gz"
},
"imgui": {
"enabled": false
"enabled": true
},
"reactphysics": {
"timescale": 0.01666666666,

View File

@ -5,7 +5,9 @@
"import": "/model.json",
"assets": [
// "/burger/burger.glb"
"/burger/burger/graph.json"
// "/burger/burger_simpler.glb"
// "/burger/burger/graph.json"
"/burger/burger_simpler/graph.json"
],
"behaviors": [],
"transform": {

View File

@ -4,7 +4,7 @@
"assets": [
],
"transform": {
"track": "parent",
// "track": "parent",
"position": [ 0, 1.7, 0 ]
},
"system": {
@ -16,7 +16,7 @@
"light": {
"type": "point",
"color": [1, 1, 1],
"power": 15,
"power": 30,
"fov": 90,
"bias": {
"constant": 1.25,

View File

@ -1,12 +1,51 @@
local timer = Timer.new()
if not timer:running() then timer:start(); end
local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata")
local transform = ent:getComponent("Transform")
local physicsState = ent:getComponent("PhysicsState")
local camera = ent:getComponent("Camera")
local cameraTransform = camera:getTransform()
-- setup all timers
local timers = {
use = Timer.new(),
holp = Timer.new(),
flashlight = Timer.new(),
physcannon = Timer.new()
}
if not timers.use:running() then timers.use:start(); end
if not timers.holp:running() then timers.holp:start(); end
if not timers.flashlight:running() then timers.flashlight:start(); end
if not timers.physcannon:running() then timers.physcannon:start(); end
-- setup held object locals
local heldObject = {
uid = 0,
distance = 0,
smoothSpeed = 4,
scrollSpeed = 16,
momentum = Vector3f(0,0,0),
rotate = false,
}
-- setup light locals
local light = {
entity = nil
}
for k, v in pairs(ent:getChildren()) do
if v:name() == "Light" then
light.entity = v
end
end
if light.entity == nil then
light.entity = ent:loadChild("./playerLight.json",true)
end
light.metadata = light.entity:getComponent("Metadata")
light.transform = light.entity:getComponent("Transform")
light.power = light.metadata["light"]["power"]
light.origin = Vector3f(light.transform.position)
light.entity:setComponent("Metadata", { light = { power = 0 } })
-- sound emitter
local playSound = function( key, loop )
if not loop then loop = false end
local url = "/ui/" .. key .. ".ogg"
@ -25,19 +64,82 @@ local stopSound = function( key )
}, 0)
end
local heldObject = {
uid = 0,
distance = 0,
smoothSpeed = 4,
scrollSpeed = 16,
momentum = Vector3f(0,0,0)
}
local useDistance = 6
local pullDistance = useDistance * 4
-- on tick
ent:bind( "tick", function(self)
if heldObject.uid ~= 0 then
local wheel = inputs.analog("MouseWheel")
-- eye transform
local flattenedTransform = cameraTransform:flatten()
flattenedTransform.forward = ( transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 ) ):normalize();
-- toggle flashlight
light.transform.position = flattenedTransform.position + flattenedTransform.forward * 2
if timers.flashlight:elapsed() > 0.5 and inputs.key("F") then
timers.flashlight:reset()
local metadata = { light = { power = light.power } }
if light.entity:getComponent("Metadata")["light"]["power"] ~= light.power then
metadata["light"]["power"] = light.power
else
metadata["light"]["power"] = 0
end
light.entity:setComponent("Metadata", metadata)
playSound("flashlight")
end
-- fire use ray
if timers.use:elapsed() > 0.5 and inputs.key("E") then
timers.use:reset()
local center = flattenedTransform.position
local direction = flattenedTransform.forward * useDistance
local prop, depth = physicsState:rayCast( center, direction )
local payload = {
user = ent:uid(),
uid = prop and prop:uid() or 0,
depth = depth,
}
if prop then
prop:callHook("entity:Use.%UID%", payload)
end
ent:callHook("entity:Use.%UID%", payload)
end
-- update HOLP
if heldObject.uid == 0 then
local mouse2 = inputs.key("Mouse2");
if mouse2 then
--[[
local center = transform.position + cameraTransform.position
local direction = transform.forward + Vector3f( 0, cameraTransform.forward.y, 0 )
direction = direction:normalize() * 4
]]
local center = flattenedTransform.position
local direction = flattenedTransform.forward * pullDistance
local prop, depth = physicsState:rayCast( center, direction )
if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then
local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState")
local strength = 500
local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude()
heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * -heldObjectPhysicsState:getMass() * strength / distanceSquared )
if timers.physcannon:elapsed() > 1.0 then
timers.physcannon:reset()
playSound("phys_tooHeavy")
end
end
end
else
local mouse1 = inputs.key("Mouse1");
local mouse3 = inputs.key("Mouse3");
local wheel = inputs.analog("MouseWheel")
if wheel ~= 0 then
heldObject.distance = heldObject.distance + (wheel / 120 * heldObject.scrollSpeed) * time.delta()
end
@ -48,27 +150,38 @@ ent:bind( "tick", function(self)
local prop = entities.get( heldObject.uid )
local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState")
if heldObject.rotate then
heldObjectTransform.orientation = transform.orientation
end
local transform = cameraTransform:flatten()
local forward = transform.orientation:rotate( Vector3f(0,0,1) ) * heldObject.distance
if heldObject.smoothSpeed ~= 0 then
local target = transform.position + forward
local offset = target - heldObjectTransform.position
local delta = offset * time.delta() * heldObject.smoothSpeed
local distance = delta:norm()
if mouse1 and timers.physcannon:elapsed() > 0.5 then
timers.physcannon:reset()
if distance > 0.001 then
heldObjectTransform.position = heldObjectTransform.position + delta
heldObject.momentum = offset * 1000
else
heldObjectTransform.position = target
end
heldObject.uid = 0
heldObjectPhysicsState:enableGravity(true)
heldObjectPhysicsState:applyImpulse( flattenedTransform.forward * heldObjectPhysicsState:getMass() * 1000 )
playSound("phys_launch"..math.random(1,4))
else
heldObjectTransform.position = transform.position + forward
if heldObject.rotate then
heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - flattenedTransform.position):normalize(), transform.up )
end
local forward = flattenedTransform.forward * heldObject.distance --flattenedTransform.orientation:rotate( Vector3f(0,0,1) )
if heldObject.smoothSpeed ~= 0 then
local target = flattenedTransform.position + forward
local offset = target - heldObjectTransform.position
local delta = offset * time.delta() * heldObject.smoothSpeed
local distance = delta:norm()
if distance > 0.001 then
if timers.holp:elapsed() > 0.125 then
timers.holp:reset()
heldObjectPhysicsState:setVelocity( delta * 20 )
end
else
heldObjectPhysicsState:setVelocity( Vector3f(0,0,0) )
end
else
heldObjectTransform.position = flattenedTransform.position + forward
end
end
end
end )
@ -102,7 +215,7 @@ ent:addHook( "entity:Use.%UID%", function( payload )
heldObject.momentum = Vector3f(0,0,0)
elseif payload.uid ~= 0 then
local hit = entities.get( heldObject.uid )
validUse = not string.match( hit:name(), "/^worldspawn_/" )
validUse = not string.matched( hit:name(), "/^worldspawn/" )
end
if validUse then

View File

@ -7,7 +7,7 @@
// { "filename": "./models/sh_mcd/graph.json" }
// { "filename": "./models/mcdonalds.glb" }
{ "filename": "./models/mcdonalds/graph.json" },
{ "filename": "./models/mcdonalds/graph.json" }
// { "filename": "./models/mini_mcd.glb" }
// { "filename": "./models/mini_mcd/graph.json" }
@ -15,7 +15,7 @@
// { "filename": "/cornell/cornell.glb" }
// { "filename": "/cornell/cornell/graph.json" }
{ "filename": "/burger.json" }
// { "filename": "/burger.json" }
],
"metadata": {
"model": {
@ -38,7 +38,6 @@
"physics": { "type": "mesh", "static": true },
"grid": { "size": [6,1,6], "epsilon": 1.0, "cleanup": true, "print": true }
},
// "worldspawn_sh2": { "physics": { "type": "mesh", "static": 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] } } },

View File

@ -318,5 +318,8 @@ struct Triangle {
struct RayTracePayload {
bool hit;
Triangle triangle;
uint instanceID;
uint primitiveID;
vec2 attributes;
// Triangle triangle;
};

View File

@ -13,6 +13,7 @@ layout (constant_id = 3) const uint CASCADES = 1;
#define PBR 1
#define VXGI 0
#define RAYTRACE 1
#define BUFFER_REFERENCE 1
#define FOG 0
#define BLOOM 0
#define WHITENOISE 0
@ -41,27 +42,42 @@ layout (binding = 2) uniform UBO {
layout (std140, binding = 3) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 4) readonly buffer Materials {
layout (std140, binding = 4) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 5) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 5) readonly buffer Textures {
layout (std140, binding = 6) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 6) readonly buffer Lights {
layout (std140, binding = 7) readonly buffer Lights {
Light lights[];
};
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 9) uniform sampler3D samplerNoise;
layout (binding = 8) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 9) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 10) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 10) uniform usampler3D voxelId[CASCADES];
layout (binding = 11) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 12) uniform sampler3D voxelRadiance[CASCADES];
layout (binding = 11) uniform usampler3D voxelId[CASCADES];
layout (binding = 12) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 13) uniform sampler3D voxelRadiance[CASCADES];
#endif
layout (location = 0) rayPayloadEXT RayTracePayload payload;
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
#include "../common/functions.h"
#include "../common/light.h"
#include "../common/fog.h"
@ -69,6 +85,65 @@ layout (location = 0) rayPayloadEXT RayTracePayload payload;
#include "../common/vxgi.h"
#endif
Triangle parsePayload( RayTracePayload payload ) {
Triangle triangle;
triangle.instanceID = payload.instanceID;
if ( !payload.hit ) return triangle;
const vec3 bary = vec3(
1.0 - payload.attributes.x - payload.attributes.y,
payload.attributes.x,
payload.attributes.y
);
const InstanceAddresses instanceAddresses = instanceAddresses[triangle.instanceID];
if ( !(0 < instanceAddresses.index) ) return triangle;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = payload.primitiveID + (drawCommand.indexID / 3);
Vertex points[3];
uvec3 indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/indices[_] += drawCommand.vertexID;
if ( 0 < instanceAddresses.vertex ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_] = vertices.v[/*triangle.*/indices[_]];
} else {
if ( 0 < instanceAddresses.position ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].position = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.uv ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].uv = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.st ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].st = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.normal ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].normal = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.tangent ) {
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent = buf.v[/*triangle.*/indices[_]];
}
}
triangle.point.position = /*triangle.*/points[0].position * bary[0] + /*triangle.*/points[1].position * bary[1] + /*triangle.*/points[2].position * bary[2];
triangle.point.uv = /*triangle.*/points[0].uv * bary[0] + /*triangle.*/points[1].uv * bary[1] + /*triangle.*/points[2].uv * bary[2];
triangle.point.st = /*triangle.*/points[0].st * bary[0] + /*triangle.*/points[1].st * bary[1] + /*triangle.*/points[2].st * bary[2];
triangle.point.normal = /*triangle.*/points[0].normal * bary[0] + /*triangle.*/points[1].normal * bary[1] + /*triangle.*/points[2].normal * bary[2];
triangle.point.tangent = /*triangle.*/points[0].tangent * bary[0] + /*triangle.*/points[1].tangent * bary[1] + /*triangle.*/points[2].tangent * bary[2];
triangle.geomNormal = normalize(cross(points[1].position - points[0].position, points[2].position - points[0].position));
return triangle;
}
void trace( Ray ray, float tMin, float tMax ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
@ -110,38 +185,39 @@ float shadowFactor( const Light light, float def ) {
}
void setupSurface( RayTracePayload payload ) {
const Instance instance = instances[payload.triangle.instanceID];
const Triangle triangle = parsePayload( payload );
const Instance instance = instances[triangle.instanceID];
surface.instance = instance;
surface.fragment = vec4(0);
surface.light = vec4(0);
// bind position
{
surface.position.world = vec3( instance.model * vec4(payload.triangle.point.position, 1.0 ) );
surface.position.world = vec3( instance.model * vec4(triangle.point.position, 1.0 ) );
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.position.world, 1.0) );
}
// bind normals
{
surface.normal.world = normalize(vec3( instance.model * vec4(payload.triangle.point.normal, 0.0 ) ));
surface.normal.world = normalize(vec3( instance.model * vec4(triangle.point.normal, 0.0 ) ));
// surface.normal.world = faceforward( surface.normal.world, surface.ray.direction, surface.normal.world );
// surface.normal.eye = normalize(vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) ));
// surface.tbn[0] = normalize(vec3( instance.model * vec4(payload.triangle.tbn[0], 0.0 ) ));
// surface.tbn[1] = normalize(vec3( instance.model * vec4(payload.triangle.tbn[1], 0.0 ) ));
// surface.tbn[0] = normalize(vec3( instance.model * vec4(triangle.tbn[0], 0.0 ) ));
// surface.tbn[1] = normalize(vec3( instance.model * vec4(triangle.tbn[1], 0.0 ) ));
// surface.tbn[2] = surface.normal.world;
vec3 tangent = normalize(vec3( instance.model * vec4(payload.triangle.point.tangent, 0.0) ));
vec3 bitangent = normalize(vec3( instance.model * vec4(cross( payload.triangle.point.normal, payload.triangle.point.tangent ), 0.0) ));
if ( payload.triangle.point.tangent != vec3(0) ) {
surface.tbn = mat3(tangent, bitangent, payload.triangle.point.normal);
vec3 tangent = normalize(vec3( instance.model * vec4(triangle.point.tangent, 0.0) ));
vec3 bitangent = normalize(vec3( instance.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
if ( triangle.point.tangent != vec3(0) ) {
surface.tbn = mat3(tangent, bitangent, triangle.point.normal);
} else {
surface.tbn = mat3(1);
}
}
// bind UVs
{
surface.uv.xy = payload.triangle.point.uv;
surface.st.xy = payload.triangle.point.st;
surface.uv.xy = triangle.point.uv;
surface.st.xy = triangle.point.st;
}
const Material material = materials[surface.instance.materialID];

View File

@ -18,7 +18,7 @@ layout (constant_id = 2) const uint CUBEMAPS = 128;
#include "../common/macros.h"
#include "../common/structs.h"
/*
layout (std140, binding = 10) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
@ -34,20 +34,25 @@ layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
*/
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
payload.hit = true;
payload.instanceID = gl_InstanceCustomIndexEXT;
payload.primitiveID = gl_PrimitiveID;
payload.attributes = attribs;
#if 0
const vec3 bary = vec3(
1.0 - attribs.x - attribs.y,
attribs.x,
attribs.y
);
const uint instanceID = gl_InstanceCustomIndexEXT;
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !(0 < instanceAddresses.index) ) return;
@ -108,4 +113,5 @@ void main() {
*/
payload.hit = true;
payload.triangle = triangle;
#endif
}

View File

@ -16,6 +16,7 @@ layout (constant_id = 2) const uint CUBEMAPS = 128;
#include "../common/macros.h"
#include "../common/structs.h"
/*
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
@ -31,18 +32,23 @@ layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
*/
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
payload.hit = true;
payload.instanceID = gl_InstanceCustomIndexEXT;
payload.primitiveID = gl_PrimitiveID;
payload.attributes = attribs;
#if 0
const vec3 bary = vec3(
1.0 - attribs.x - attribs.y,
attribs.x,
attribs.y
);
const uint instanceID = gl_InstanceCustomIndexEXT;
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
@ -105,4 +111,5 @@ void main() {
*/
payload.hit = true;
payload.triangle = triangle;
#endif
}

View File

@ -61,4 +61,12 @@ public:\
OBJ ## Behavior::attach( *this );\
}
#define UF_BEHAVIOR_ENTITY_CPP_END( OBJ )
#define UF_BEHAVIOR_ENTITY_CPP_END( OBJ )
#define UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS( METADATA, JSON ) {\
this->addHook( "object:Serialize.%UID%", [&]{ METADATA.serialize(self, JSON); });\
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ METADATA.serialize(self, (uf::Serializer&) json); });\
this->addHook( "object:Deserialize.%UID%", [&]{ METADATA.deserialize(self, JSON); });\
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ METADATA.deserialize(self, (uf::Serializer&) json); });\
METADATA.deserialize(self, JSON);\
}

View File

@ -11,6 +11,9 @@
#if UF_USE_LUA
#include <uf/ext/lua/lua.h>
#endif
#if UF_USE_TOML
#include <uf/ext/toml/toml.h>
#endif
namespace ext {
namespace json {
@ -18,8 +21,8 @@ namespace ext {
extern uf::stl::string PREFERRED_ENCODING;
struct UF_API EncodingSettings {
uf::stl::string compression = ""; // auto-assume compression scheme
uf::stl::string encoding = ""; // auto-assume re-encoding scheme
uf::stl::string compression = ""; // auto-assume compression scheme
bool pretty = false;
bool quantize = false;
uint8_t precision = 0;
@ -101,6 +104,12 @@ T& ext::json::encode( const ext::json::Value& json, T& output, const ext::json::
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
uf::stl::string buffer = ext::toml::fromJson( json.dump() );
output = T( buffer.begin(), buffer.end() );
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);
@ -129,6 +138,15 @@ ext::json::Value& ext::json::decode( ext::json::Value& json, const T& input, con
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
// UF_MSG_DEBUG("TOML: {}", std::string_view{ (const char*) input.data(), input.size() });
T parsed = ext::toml::toJson( input );
// UF_MSG_DEBUG("JSON: {}", std::string_view{ (const char*) parsed.data(), parsed.size() });
json = nlohmann::json::parse(parsed, nullptr, exceptions, comments);
// UF_MSG_DEBUG("ENCODED: {}", json.dump());
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);

View File

@ -104,11 +104,18 @@ namespace ext {
void UF_API applyRotation( pod::PhysicsState&, const pod::Vector3f&, float );
// ray casting
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& );
float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, uf::Object*& );
uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& );
uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f& );
uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f&, float& );
uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, float& );
// float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, uf::Object*& );
// allows noclip
void UF_API activateCollision( pod::PhysicsState&, bool = true );
//
float UF_API getMass( pod::PhysicsState& );
void UF_API setMass( pod::PhysicsState&, float );
}
}
#endif

View File

@ -0,0 +1,17 @@
#pragma once
#include <uf/config.h>
#include <uf/utils/memory/vector.h>
#if UF_USE_TOML
namespace ext {
namespace toml {
uf::stl::string toJson( const uf::stl::string& );
uf::stl::vector<uint8_t> toJson( const uf::stl::vector<uint8_t>& );
uf::stl::string fromJson( const uf::stl::string& );
uf::stl::vector<uint8_t> fromJson( const uf::stl::vector<uint8_t>& );
}
}
#endif

View File

@ -50,6 +50,7 @@ namespace ext {
bool update( const void*, VkDeviceSize, bool = VK_DEFAULT_STAGE_BUFFERS ) const;
void destroy();
void swap( Buffer& );
Buffer alias() const;
void aliasBuffer( const Buffer& );
};

View File

@ -40,6 +40,8 @@ namespace ext {
extern UF_API PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR;
extern UF_API PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR;
extern UF_API PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR;
extern UF_API PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR;
extern UF_API PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR;
uf::stl::string errorString( VkResult result );
VkSampleCountFlagBits sampleCount( uint8_t );
@ -47,13 +49,16 @@ namespace ext {
typedef VmaAllocator Allocator;
namespace settings {
constexpr size_t maxViews = 6;
extern UF_API uint32_t width;
extern UF_API uint32_t height;
extern UF_API uint8_t msaa;
extern UF_API bool validation;
extern UF_API size_t viewCount;
extern UF_API size_t gpuID;
constexpr size_t maxViews = 6;
extern UF_API size_t scratchBufferAlignment;
extern UF_API size_t scratchBufferInitialSize;
extern UF_API uf::stl::vector<uf::stl::string> validationFilters;
extern UF_API uf::stl::vector<uf::stl::string> requestedDeviceFeatures;
@ -122,6 +127,8 @@ namespace ext {
extern UF_API uf::stl::unordered_map<uf::stl::string, RenderMode*> renderModesMap;
extern UF_API uf::ThreadUnique<RenderMode*> currentRenderMode;
extern UF_API Buffer scratchBuffer;
bool UF_API hasRenderMode( const uf::stl::string&, bool = true );
RenderMode& UF_API addRenderMode( RenderMode*, const uf::stl::string& = "" );
RenderMode& UF_API getRenderMode( const uf::stl::string&, bool = true );

View File

@ -65,6 +65,7 @@ namespace uf {
}
static uf::stl::string resolveFilename( const uf::stl::string& filename, bool compareTimes = true );
static uf::stl::string resolveFilename( const uf::stl::string& filename, const ext::json::EncodingSettings&, bool compareTimes = true );
bool readFromFile( const uf::stl::string& from, const uf::stl::string& hash = "" );
bool writeToFile( const uf::stl::string& to, const ext::json::EncodingSettings& = {} ) const;

View File

@ -109,6 +109,7 @@ uf::Asset::Payload uf::Asset::resolveToPayload( const uf::stl::string& uri, cons
{ "msgpack",uf::Asset::Type::JSON },
{ "ubjson", uf::Asset::Type::JSON },
{ "bjdata", uf::Asset::Type::JSON },
{ "toml", uf::Asset::Type::JSON },
{ "lua", uf::Asset::Type::LUA },
@ -129,6 +130,7 @@ uf::Asset::Payload uf::Asset::resolveToPayload( const uf::stl::string& uri, cons
else if ( basename == "graph.msgpack" ) payload.type = uf::Asset::Type::GRAPH;
else if ( basename == "graph.ubjson" ) payload.type = uf::Asset::Type::GRAPH;
else if ( basename == "graph.bjdata" ) payload.type = uf::Asset::Type::GRAPH;
else if ( basename == "graph.toml" ) payload.type = uf::Asset::Type::GRAPH;
return payload;
}

View File

@ -59,7 +59,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
if ( json["type"].as<uf::stl::string>() == "merge" ) metadataJson.merge(json["value"], true);
else if ( json["type"].as<uf::stl::string>() == "import" ) metadataJson.import(json["value"]);
else if ( json["path"].is<uf::stl::string>() ) metadataJson.path(json["path"].as<uf::stl::string>()) = json["value"];
else metadataJson.merge(json, true);
// else metadataJson.merge(json, true);
});
this->addHook( "asset:QueueLoad.%UID%", [&](pod::payloads::assetLoad& payload){
uf::stl::string callback = this->formatHookName("asset:FinishedLoad.%UID%");
@ -97,9 +97,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
}
});
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
if ( ext::json::isObject(metadataJson["physics"]) ) {
auto& collider = this->getComponent<pod::PhysicsState>();
@ -247,7 +245,7 @@ void uf::ObjectBehavior::Metadata::serialize( uf::Object& self, uf::Serializer&
if ( /*this->*/transform.trackParent ) serializer["system"]["transform"]["track"] = "parent";
}
void uf::ObjectBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {
/*this->*/transform.initial = self.getComponent<pod::Transform<>>();
/*this->*/transform.trackParent = serializer["system"]["transform"]["track"].as<uf::stl::string>() == "parent";
if ( !transform.trackParent ) /*this->*/transform.initial = self.getComponent<pod::Transform<>>();
/*this->*/transform.trackParent = serializer["system"]["transform"]["track"].as<uf::stl::string>(/*this->*/transform.trackParent ? "parent" : "") == "parent";
}
UF_BEHAVIOR_ENTITY_CPP_END(Object)

View File

@ -40,11 +40,17 @@ namespace binds {
if ( type == "Metadata" ) {
auto encoded = ext::lua::encode( value.as<sol::table>() );
if ( encoded ) {
/*
self.callHook( "object:Serialize.%UID%" );
auto& metadata = self.getComponent<uf::Serializer>();
uf::stl::string str = encoded.value();
metadata.merge( str, false );
self.callHook( "object:Deserialize.%UID%" );
*/
uf::stl::string str = encoded.value();
ext::json::Value json;
ext::json::decode( json, str );
self.callHook( "object:Deserialize.%UID%", json );
}
}
UF_LUA_UPDATE_COMPONENT(pod::Transform<>)

View File

@ -13,6 +13,13 @@ namespace binds {
if ( !state.body ) return;
state.body->enableGravity(s);
}
std::tuple<uf::Object*, float> rayCast( pod::Physics& self, const pod::Vector3f& center, const pod::Vector3f& direction ) {
float depth = -1;
uf::Object* object = uf::physics::impl::rayCast(self, center, direction, depth);
return std::make_tuple( object, depth );
}
}
UF_LUA_REGISTER_USERTYPE(pod::Physics,
@ -31,7 +38,12 @@ UF_LUA_REGISTER_USERTYPE(pod::PhysicsState,
UF_LUA_REGISTER_USERTYPE_DEFINE( applyVelocity, UF_LUA_C_FUN(uf::physics::impl::applyVelocity) ),
// UF_LUA_REGISTER_USERTYPE_DEFINE( applyRotation, UF_LUA_C_FUN(uf::physics::impl::applyRotation) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( enableGravity, UF_LUA_C_FUN(::binds::enableGravity) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(uf::physics::impl::activateCollision) )
UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(uf::physics::impl::activateCollision) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( rayCast, UF_LUA_C_FUN(::binds::rayCast) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( getMass, UF_LUA_C_FUN(uf::physics::impl::getMass) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( setMass, UF_LUA_C_FUN(uf::physics::impl::setMass) )
)
#endif

View File

@ -572,28 +572,32 @@ void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Vect
// ray casting
float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction ) {
if ( !::world )
return -1;
::RaycastCallback callback;
::world->raycast( rp3d::Ray( ::convert( center ), ::convert( center + direction ) ), &callback );
if ( !callback.isHit ) return -1;
return callback.raycastInfo.hitFraction;
uf::Object* ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction ) {
float depth = -1;
return rayCast( center, direction, NULL, depth );
}
float ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object* source, uf::Object*& object ) {
if ( !::world )
return -1;
uf::Object* ext::reactphysics::rayCast( pod::PhysicsState& state, const pod::Vector3f& center, const pod::Vector3f& direction ) {
float depth = -1;
return rayCast( center, direction, state.object, depth );
}
uf::Object* ext::reactphysics::rayCast( pod::PhysicsState& state, const pod::Vector3f& center, const pod::Vector3f& direction, float& depth ) {
return rayCast( center, direction, state.object, depth );
}
uf::Object* ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object* source, float& depth ) {
depth = -1;
if ( !::world ) return NULL;
::RaycastCallback callback;
callback.source = source;
::world->raycast( rp3d::Ray( ::convert( center ), ::convert( center + direction ) ), &callback );
object = NULL;
if ( !callback.isHit ) {
return -1;
}
object = (uf::Object*) callback.raycastInfo.body->getUserData();
return callback.raycastInfo.hitFraction;
if ( !callback.isHit ) return NULL;
depth = callback.raycastInfo.hitFraction;
return (uf::Object*) callback.raycastInfo.body->getUserData();
}
// allows noclip
@ -608,4 +612,14 @@ void ext::reactphysics::activateCollision( pod::PhysicsState& state, bool s ) {
}
}
float ext::reactphysics::getMass( pod::PhysicsState& state ) {
if ( !state.body ) return state.stats.mass;
return (state.stats.mass = state.body->getMass());
}
void ext::reactphysics::setMass( pod::PhysicsState& state, float mass ) {
state.stats.mass = mass;
state.body->setMass(mass);
}
#endif

View File

@ -0,0 +1,157 @@
#if UF_USE_TOML
#define TOML_HEADER_ONLY 0
#define TOML_ENABLE_FORMATTERS 1
#define TOML_IMPLEMENTATION
#if UF_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#elif UF_NO_EXCEPTIONS
#define TOML_EXCEPTIONS 0
#else
#define TOML_EXCEPTIONS 0
#endif
#include <toml++/toml.h>
#include <uf/ext/toml/toml.h>
#include <uf/ext/json/json.h>
#include <uf/utils/serialize/serializer.h>
using namespace std::string_view_literals;
TOML_NAMESPACE_START
{
template<typename T>
static void from_json(const ext::json::Value& j, value<T>& val) {
assert(j.is<T>());
*val = j.as<T>();
}
static void from_json(const ext::json::Value&, array&);
template <typename T, typename Key>
static void insert_from_json(table & tbl, Key && key, const ext::json::Value& val) {
T v;
from_json(val, v);
tbl.insert_or_assign(static_cast<Key&&>(key), std::move(v));
}
template <typename T>
static void insert_from_json(array & arr, const ext::json::Value& val) {
T v;
from_json(val, v);
arr.push_back(std::move(v));
}
static void from_json(const ext::json::Value& j, table& tbl) {
if ( j.is_null() ) return;
if( !j.is_object() ) {
UF_MSG_ERROR("ERROR: {}", j.dump());
return;
}
ext::json::forEach(j, [&]( const uf::stl::string& k, const ext::json::Value& v ){
if ( v.is<std::string>() ) insert_from_json<toml::value<std::string>>(tbl, k, v);
else if ( v.is<double>(true) ) insert_from_json<toml::value<double>>(tbl, k, v);
else if ( v.is<int64_t>() ) insert_from_json<toml::value<int64_t>>(tbl, k, v);
else if ( v.is<bool>() ) insert_from_json<toml::value<bool>>(tbl, k, v);
else if (v.is_array()) insert_from_json<toml::array>(tbl, k, v);
else insert_from_json<toml::table>(tbl, k, v);
});
}
static void from_json(const ext::json::Value& j, array& arr) {
ext::json::forEach(j, [&]( const ext::json::Value& v ){
if ( v.is<std::string>() )
insert_from_json<toml::value<std::string>>(arr, v);
else if ( v.is<double>(true) ) insert_from_json<toml::value<double>>(arr, v);
else if ( v.is<int64_t>() ) insert_from_json<toml::value<int64_t>>(arr, v);
else if ( v.is<bool>() ) insert_from_json<toml::value<bool>>(arr, v);
else if (v.is_array()) insert_from_json<toml::array>(arr, v);
else insert_from_json<toml::table>(arr, v);
});
}
}
TOML_NAMESPACE_END;
uf::stl::string UF_API ext::toml::fromJson( const uf::stl::string& source ) {
ext::json::Value j;
ext::json::decode( j, source );
#if UF_EXCEPTIONS
try {
#endif
::toml::table tbl;
::toml::from_json( j, tbl );
std::stringstream ss; ss << tbl;
return ss.str();
#if UF_EXCEPTIONS
} catch ( const ::toml::parse_error& err ) {
UF_MSG_ERROR("TOML error: {}", e.what());
}
return "";
#endif
}
uf::stl::vector<uint8_t> UF_API ext::toml::fromJson( const uf::stl::vector<uint8_t>& source ) {
ext::json::Value j;
ext::json::decode( j, source );
#if UF_EXCEPTIONS
try {
#endif
::toml::table tbl;
::toml::from_json( j, tbl );
std::stringstream ss; ss << tbl;
uf::stl::string str = ss.str();
return uf::stl::vector<uint8_t>{ str.begin(), str.end() };
#if UF_EXCEPTIONS
} catch ( const ::toml::parse_error& err ) {
UF_MSG_ERROR("TOML error: {}", e.what());
}
return {};
#endif
}
uf::stl::string UF_API ext::toml::toJson( const uf::stl::string& source ) {
#if UF_EXCEPTIONS
try {
#endif
::toml::parse_result result = ::toml::parse( source );
if ( !result ) {
std::stringstream error; error << result.error();
UF_MSG_ERROR("TOML error: {}", error.str());
return "";
}
std::stringstream ss; ss << ::toml::json_formatter{ result };
return ss.str();
#if UF_EXCEPTIONS
} catch ( const ::toml::parse_error& err ) {
UF_MSG_ERROR("TOML error: {}", e.what());
}
return "";
#endif
}
uf::stl::vector<uint8_t> UF_API ext::toml::toJson( const uf::stl::vector<uint8_t>& source ) {
#if UF_EXCEPTIONS
try {
#endif
std::string_view source_view( (const char*) source.data(), source.size() );
::toml::parse_result result = ::toml::parse( source_view );
if ( !result ) {
std::stringstream error; error << result.error();
UF_MSG_ERROR("TOML error: {}", error.str());
return {};
}
std::stringstream ss; ss << ::toml::json_formatter{ result };
uf::stl::string str = ss.str();
return uf::stl::vector<uint8_t>{ str.begin(), str.end() };
#if UF_EXCEPTIONS
} catch ( const ::toml::parse_error& err ) {
UF_MSG_ERROR("TOML error: {}", e.what());
}
return {};
#endif
}
#endif

View File

@ -7,6 +7,20 @@
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/device.h>
void ext::vulkan::Buffer::swap( ext::vulkan::Buffer& buffer ) {
std::swap(this->aliased, buffer.aliased);
std::swap(this->device, buffer.device);
std::swap(this->buffer, buffer.buffer);
std::swap(this->memory, buffer.memory);
std::swap(this->descriptor, buffer.descriptor);
std::swap(this->alignment, buffer.alignment);
std::swap(this->address, buffer.address);
std::swap(this->mapped, buffer.mapped);
std::swap(this->usage, buffer.usage);
std::swap(this->memoryProperties, buffer.memoryProperties);
std::swap(this->allocation, buffer.allocation);
std::swap(this->allocationInfo, buffer.allocationInfo);
}
ext::vulkan::Buffer ext::vulkan::Buffer::alias() const {
ext::vulkan::Buffer buffer;
buffer.aliasBuffer(*this);

View File

@ -1150,6 +1150,8 @@ void ext::vulkan::Device::initialize() {
vkCmdTraceRaysKHR = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
vkGetRayTracingShaderGroupHandlesKHR = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
vkCreateRayTracingPipelinesKHR = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
vkCmdWriteAccelerationStructuresPropertiesKHR = reinterpret_cast<PFN_vkCmdWriteAccelerationStructuresPropertiesKHR>(vkGetDeviceProcAddr(device, "vkCmdWriteAccelerationStructuresPropertiesKHR"));
vkCmdCopyAccelerationStructureKHR = reinterpret_cast<PFN_vkCmdCopyAccelerationStructureKHR>(vkGetDeviceProcAddr(device, "vkCmdCopyAccelerationStructureKHR"));
}
}

View File

@ -29,6 +29,8 @@ PFN_vkGetAccelerationStructureDeviceAddressKHR ext::vulkan::vkGetAccelerationStr
PFN_vkCmdTraceRaysKHR ext::vulkan::vkCmdTraceRaysKHR = NULL; // = reinterpret_cast<PFN_vkCmdTraceRaysKHR>(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR"));
PFN_vkGetRayTracingShaderGroupHandlesKHR ext::vulkan::vkGetRayTracingShaderGroupHandlesKHR = NULL; // = reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesKHR>(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR"));
PFN_vkCreateRayTracingPipelinesKHR ext::vulkan::vkCreateRayTracingPipelinesKHR = NULL; // = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
PFN_vkCmdWriteAccelerationStructuresPropertiesKHR ext::vulkan::vkCmdWriteAccelerationStructuresPropertiesKHR = NULL; // = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
PFN_vkCmdCopyAccelerationStructureKHR ext::vulkan::vkCmdCopyAccelerationStructureKHR = NULL; // = reinterpret_cast<PFN_vkCreateRayTracingPipelinesKHR>(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR"));
void ext::vulkan::Pipeline::initialize( const Graphic& graphic ) {
return this->initialize( graphic, graphic.descriptor );
@ -1180,12 +1182,10 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
const VkAccelerationStructureBuildRangeInfoKHR* rangeInfo;
uf::renderer::AccelerationStructure as;
uf::renderer::AccelerationStructure cleanup;
};
uf::stl::vector<BlasData> blasDatas;
uf::renderer::Buffer scratchBuffer;
uf::renderer::Buffer blasBuffer;
// setup BLAS geometry
{
auto& mesh = this->descriptor.inputs;
@ -1299,8 +1299,11 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
}
}
bool shouldCompact = true;
// determine BLAS size and its scratch buffer
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
if ( shouldCompact) flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
size_t totalBlasBufferSize{};
size_t maxScratchBufferSize{};
for ( auto& blasData : blasDatas ) {
@ -1328,72 +1331,140 @@ void ext::vulkan::Graphic::generateBottomAccelerationStructures() {
totalBlasBufferSize += blasData.sizeInfo.accelerationStructureSize;
}
#define VK_UNIFIED_BLAS_BUFFER 1
#if VK_UNIFIED_BLAS_BUFFER
// create BLAS buffer and handle
size_t blasBufferIndex = this->initializeBuffer( NULL, totalBlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
size_t blasBufferOffset = 0;
this->metadata.buffers["blasBuffer"] = blasBufferIndex;
#endif
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, maxScratchBufferSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
for ( auto& blasData : blasDatas ) {
#if VK_UNIFIED_BLAS_BUFFER
blasData.as.buffer = this->buffers[blasBufferIndex].alias();
blasData.as.buffer.descriptor.offset = blasBufferOffset;
VkQueryPool queryPool{VK_NULL_HANDLE};
if ( shouldCompact ) {
VkQueryPoolCreateInfo queryPoolCreateInfo{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
queryPoolCreateInfo.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
queryPoolCreateInfo.queryCount = blasDatas.size();
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = blasData.sizeInfo.accelerationStructureSize;
createInfo.buffer = blasData.as.buffer.buffer;
createInfo.offset = blasData.as.buffer.descriptor.offset;
blasBufferOffset += blasData.sizeInfo.accelerationStructureSize;
#else
size_t blasBufferIndex = this->initializeBuffer( NULL, blasData.sizeInfo.accelerationStructureSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
blasData.as.buffer = this->buffers[blasBufferIndex].alias();
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = blasData.sizeInfo.accelerationStructureSize;
createInfo.buffer = blasData.as.buffer.buffer;
createInfo.offset = blasData.as.buffer.descriptor.offset;
#endif
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &blasData.as.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blasData.as.handle;
blasData.as.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
// write to BLAS
blasData.buildInfo.dstAccelerationStructure = blasData.as.handle;
blasData.buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&blasData.buildInfo,
&blasData.rangeInfo
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolCreateInfo, nullptr, &queryPool));
vkResetQueryPool(device, queryPool, 0, blasDatas.size());
}
for ( auto& blasData : blasDatas ) this->accelerationStructures.bottoms.emplace_back(blasData.as);
uint32_t queryCount{};
{
size_t blasBufferOffset = 0;
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.update( NULL, maxScratchBufferSize );
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
for ( auto& blasData : blasDatas ) {
blasData.as.buffer = this->buffers[blasBufferIndex].alias();
blasData.as.buffer.descriptor.offset = blasBufferOffset;
blasBufferOffset += blasData.sizeInfo.accelerationStructureSize;
scratchBuffer.destroy();
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = blasData.sizeInfo.accelerationStructureSize;
createInfo.buffer = blasData.as.buffer.buffer;
createInfo.offset = blasData.as.buffer.descriptor.offset;
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &blasData.as.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blasData.as.handle;
blasData.as.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
// write to BLAS
blasData.buildInfo.dstAccelerationStructure = blasData.as.handle;
blasData.buildInfo.scratchData.deviceAddress = scratchBuffer.getAddress();
uf::renderer::vkCmdBuildAccelerationStructuresKHR(
commandBuffer,
1,
&blasData.buildInfo,
&blasData.rangeInfo
);
// pipeline barrier here for scratch buffer
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
if ( queryPool ) uf::renderer::vkCmdWriteAccelerationStructuresPropertiesKHR(
commandBuffer,
1,
&blasData.buildInfo.dstAccelerationStructure,
VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
queryPool,
queryCount++
);
}
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
}
// compact
if ( queryPool ) {
uf::stl::vector<VkDeviceSize> compactSizes(blasDatas.size());
vkGetQueryPoolResults(device, queryPool, 0, (uint32_t) compactSizes.size(), compactSizes.size() * sizeof(VkDeviceSize), compactSizes.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT);
size_t queryIndex{};
size_t totalBlasBufferSize{};
for ( auto& blasData : blasDatas ) {
size_t compactedSize = compactSizes[queryIndex++];
size_t oldSize = blasData.sizeInfo.accelerationStructureSize;
blasData.cleanup = blasData.as;
blasData.sizeInfo.accelerationStructureSize = ALIGNED_SIZE(compactedSize, 256);
totalBlasBufferSize += blasData.sizeInfo.accelerationStructureSize;
// UF_MSG_DEBUG("Reduced size to {}% ({} -> {} = {})", (oldSize - compactedSize) * 100.0f / oldSize, oldSize, compactedSize, oldSize - compactedSize);
}
ext::vulkan::Buffer oldBuffer;
oldBuffer.initialize( NULL, totalBlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
this->buffers[blasBufferIndex].swap(oldBuffer);
size_t blasBufferOffset{};
for ( auto& blasData : blasDatas ) {
blasData.as.buffer = this->buffers[blasBufferIndex].alias();
blasData.as.buffer.descriptor.offset = blasBufferOffset;
blasBufferOffset += blasData.sizeInfo.accelerationStructureSize;
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = blasData.sizeInfo.accelerationStructureSize;
createInfo.buffer = blasData.as.buffer.buffer;
createInfo.offset = blasData.as.buffer.descriptor.offset;
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &blasData.as.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = blasData.as.handle;
blasData.as.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
VkCopyAccelerationStructureInfoKHR copyInfo{VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR};
copyInfo.src = blasData.cleanup.handle;
copyInfo.dst = blasData.as.handle;
copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
uf::renderer::vkCmdCopyAccelerationStructureKHR(commandBuffer, &copyInfo);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
}
oldBuffer.destroy();
}
for ( auto& blasData : blasDatas ) {
this->accelerationStructures.bottoms.emplace_back(blasData.as);
if ( blasData.cleanup.handle ) uf::renderer::vkDestroyAccelerationStructureKHR(device, blasData.cleanup.handle, nullptr);
}
if ( queryPool ) vkDestroyQueryPool(device, queryPool, nullptr);
}
void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vector<uf::renderer::Graphic*>& graphics, const uf::stl::vector<pod::Instance>& instances ) {
auto& device = *this->device;
bool rebuild = false;
bool update = this->accelerationStructures.top.handle != VK_NULL_HANDLE;
bool shouldCompact = false;
VkPhysicalDeviceAccelerationStructurePropertiesKHR acclerationStructureProperties{};
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rayTracingPipelineProperties{};
@ -1409,6 +1480,16 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
vkGetPhysicalDeviceProperties2(device.physicalDevice, &deviceProperties2);
}
VkQueryPool queryPool{VK_NULL_HANDLE};
if ( shouldCompact ) {
VkQueryPoolCreateInfo queryPoolCreateInfo{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
queryPoolCreateInfo.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
queryPoolCreateInfo.queryCount = 1;
VK_CHECK_RESULT(vkCreateQueryPool(device, &queryPoolCreateInfo, nullptr, &queryPool));
vkResetQueryPool(device, queryPool, 0, 1);
}
uf::stl::vector<VkAccelerationStructureInstanceKHR> instancesVK; instancesVK.reserve( instances.size() );
for ( auto& graphic : graphics ) {
@ -1429,20 +1510,15 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
}
}
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
size_t instanceIndex{};
size_t tlasBufferIndex{};
if ( !update ) {
const size_t EXTRANEOUS_SIZE = 2048;
size_t bufferSize = MAX( instancesVK.size(), EXTRANEOUS_SIZE );
// do not stage, because apparently vkQueueWaitIdle doesn't actually wait for the transfer to complete
instanceIndex = this->initializeBuffer(
NULL, bufferSize * sizeof(VkAccelerationStructureInstanceKHR),
(const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR),
uf::renderer::enums::Buffer::ADDRESS | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, false
);
this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
this->metadata.buffers["tlasInstance"] = instanceIndex;
} else {
if ( this->metadata.buffers.count("tlasInstance") > 0 ) {
@ -1455,10 +1531,12 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
rebuild = rebuild || this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
}
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
auto& tlas = this->accelerationStructures.top;
{
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
if ( shouldCompact ) flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
uint32_t countInstance = instancesVK.size();
auto& tlas = this->accelerationStructures.top;
VkAccelerationStructureGeometryInstancesDataKHR instancesVk{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
instancesVk.data.deviceAddress = instanceBufferAddress;
@ -1518,10 +1596,9 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
tlas.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
}
// write to BLAS
uf::renderer::Buffer scratchBuffer;
// write to TLAS
scratchBuffer.alignment = acclerationStructureProperties.minAccelerationStructureScratchOffsetAlignment;
scratchBuffer.initialize( NULL, sizeInfo.buildScratchSize, uf::renderer::enums::Buffer::STORAGE | uf::renderer::enums::Buffer::ADDRESS );
scratchBuffer.update( NULL, sizeInfo.buildScratchSize );
buildInfo.srcAccelerationStructure = update ? tlas.handle : VK_NULL_HANDLE;
buildInfo.dstAccelerationStructure = tlas.handle;
@ -1537,11 +1614,63 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
&buildInfo,
&rangeInfo
);
if ( queryPool ) uf::renderer::vkCmdWriteAccelerationStructuresPropertiesKHR(
commandBuffer,
1,
&buildInfo.dstAccelerationStructure,
VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
queryPool,
0
);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
}
// compact
if ( queryPool ) {
VkDeviceSize compactSize{};
vkGetQueryPoolResults(device, queryPool, 0, 1, sizeof(VkDeviceSize), &compactSize, sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT);
auto cleanup = tlas;
size_t tlasBufferSize = ALIGNED_SIZE(compactSize, 256);
// UF_MSG_DEBUG("Reduced size to {}% ({} -> {} = {})", (float) (oldSize - compactedSize) / (float) (oldSize), oldSize, compactedSize, oldSize - compactedSize);
ext::vulkan::Buffer oldBuffer;
oldBuffer.initialize( NULL, tlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
this->buffers[tlasBufferIndex].swap(oldBuffer);
tlas.buffer = this->buffers[tlasBufferIndex].alias();
tlas.buffer.descriptor.offset = 0;
VkAccelerationStructureCreateInfoKHR createInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
createInfo.size = tlasBufferSize;
createInfo.buffer = tlas.buffer.buffer;
createInfo.offset = tlas.buffer.descriptor.offset;
VK_CHECK_RESULT(uf::renderer::vkCreateAccelerationStructureKHR(device, &createInfo, nullptr, &tlas.handle));
VkAccelerationStructureDeviceAddressInfoKHR accelerationDeviceAddressInfo{};
accelerationDeviceAddressInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
accelerationDeviceAddressInfo.accelerationStructure = tlas.handle;
tlas.deviceAddress = uf::renderer::vkGetAccelerationStructureDeviceAddressKHR(device, &accelerationDeviceAddressInfo);
VkCopyAccelerationStructureInfoKHR copyInfo{VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR};
copyInfo.src = cleanup.handle;
copyInfo.dst = tlas.handle;
copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, uf::renderer::Device::QueueEnum::COMPUTE);
uf::renderer::vkCmdCopyAccelerationStructureKHR(commandBuffer, &copyInfo);
device.flushCommandBuffer(commandBuffer, uf::renderer::Device::QueueEnum::COMPUTE);
scratchBuffer.destroy();
uf::renderer::vkDestroyAccelerationStructureKHR(device, cleanup.handle, nullptr);
oldBuffer.destroy();
}
if ( queryPool ) vkDestroyQueryPool(device, queryPool, nullptr);
if ( rebuild ) {
// uf::renderer::states::rebuild = true;
auto& renderMode = ext::vulkan::getRenderMode( descriptor.renderMode, true );
@ -1744,6 +1873,12 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
}
}
void ext::vulkan::Graphic::destroy() {
for ( auto& as : accelerationStructures.bottoms ) {
uf::renderer::vkDestroyAccelerationStructureKHR(*device, as.handle, nullptr);
}
if ( accelerationStructures.top.handle ) {
uf::renderer::vkDestroyAccelerationStructureKHR(*device, accelerationStructures.top.handle, nullptr);
}
for ( auto& pair : pipelines ) pair.second.destroy();
pipelines.clear();
material.destroy();

View File

@ -26,6 +26,8 @@ bool ext::vulkan::settings::defaultStageBuffers = true;
// constexpr size_t ext::vulkan::settings::maxViews = 6;
size_t ext::vulkan::settings::viewCount = 2;
size_t ext::vulkan::settings::gpuID = -1;
size_t ext::vulkan::settings::scratchBufferAlignment = 256;
size_t ext::vulkan::settings::scratchBufferInitialSize = 1024 * 1024;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::validationFilters;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedDeviceFeatures;
@ -81,6 +83,8 @@ bool ext::vulkan::states::rebuild = false;
uint32_t ext::vulkan::states::currentBuffer = 0;
uf::ThreadUnique<ext::vulkan::RenderMode*> ext::vulkan::currentRenderMode;
ext::vulkan::Buffer ext::vulkan::scratchBuffer;
uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::renderModes = {
new ext::vulkan::BaseRenderMode,
};
@ -251,6 +255,9 @@ void ext::vulkan::initialize() {
ext::vulkan::mutex.lock();
device.initialize();
swapchain.initialize( device );
ext::vulkan::scratchBuffer.alignment = ext::vulkan::settings::scratchBufferAlignment;
ext::vulkan::scratchBuffer.initialize( NULL, ext::vulkan::settings::scratchBufferInitialSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
if ( uf::io::exists(uf::io::root + "/textures/missing.png") ) {
uf::Image image;
@ -516,33 +523,23 @@ void ext::vulkan::destroy() {
ext::vulkan::mutex.lock();
synchronize();
for ( auto& fence : ::auxFencesGraphics ) vkDestroyFence( device, fence, nullptr);
for ( auto& fence : ::auxFencesCompute ) vkDestroyFence( device, fence, nullptr);
Texture2D::empty.destroy();
Texture3D::empty.destroy();
TextureCube::empty.destroy();
/*
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
uf::Graphic& graphic = entity->getComponent<uf::Graphic>();
graphic.destroy();
}
*/
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->device ) continue;
renderMode->destroy();
// delete renderMode;
delete renderMode;
renderMode = NULL;
}
for ( auto& s : ext::vulkan::Sampler::samplers ) {
s.destroy();
}
Texture2D::empty.destroy();
Texture3D::empty.destroy();
TextureCube::empty.destroy();
for ( auto& s : ext::vulkan::Sampler::samplers ) s.destroy();
for ( auto& fence : ::auxFencesGraphics ) vkDestroyFence( device, fence, nullptr);
for ( auto& fence : ::auxFencesCompute ) vkDestroyFence( device, fence, nullptr);
ext::vulkan::scratchBuffer.destroy();
swapchain.destroy();
device.destroy();

View File

@ -178,7 +178,7 @@ bool UF_API uf::io::exists( const uf::stl::string& _filename ) {
size_t UF_API uf::io::mtime( const uf::stl::string& _filename ) {
uf::stl::string filename = sanitize(_filename);
static struct stat buffer;
if ( stat(filename.c_str(), &buffer) != 0 ) return -1;
if ( stat(filename.c_str(), &buffer) != 0 ) return 0;
return buffer.st_mtime;
}
bool UF_API uf::io::mkdir( const uf::stl::string& _filename ) {

View File

@ -40,12 +40,18 @@ uf::Serializer::output_t uf::Serializer::serialize( const ext::json::EncodingSet
}
uf::stl::string uf::Serializer::resolveFilename( const uf::stl::string& filename, bool compareTimes ) {
return resolveFilename( filename, ext::json::EncodingSettings{
.encoding = ext::json::PREFERRED_ENCODING,
.compression = ext::json::PREFERRED_COMPRESSION,
}, compareTimes );
}
uf::stl::string uf::Serializer::resolveFilename( const uf::stl::string& filename, const ext::json::EncodingSettings& settings, bool compareTimes ) {
uf::stl::string _filename = filename;
if ( ext::json::PREFERRED_ENCODING != "" && ext::json::PREFERRED_ENCODING != "json" ) {
_filename = uf::string::replace( _filename, "/\\.json$/", "." + ext::json::PREFERRED_ENCODING );
if ( settings.encoding != "" && settings.encoding != "json" ) {
_filename = uf::string::replace( _filename, "/\\.json$/", "." + settings.encoding );
}
if ( ext::json::PREFERRED_COMPRESSION != "" ) {
_filename = _filename + "." + ext::json::PREFERRED_COMPRESSION;
if ( settings.compression != "" ) {
_filename = _filename + "." + settings.compression;
}
if ( !compareTimes ) return _filename;
@ -61,7 +67,14 @@ 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$/" ) ) {
uf::stl::string _filename = uf::Serializer::resolveFilename( filename );
#if 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);
return readFromFile( toml_filename, hash );
}
#endif
uf::stl::string _filename = resolveFilename( filename );
if ( _filename != filename ) return readFromFile( _filename, hash );
}
#endif
@ -82,12 +95,32 @@ bool uf::Serializer::readFromFile( const uf::stl::string& filename, const uf::st
else if ( uf::string::matched( filename, "/\\.msgpack/" ) ) settings.encoding = "msgpack";
else if ( uf::string::matched( filename, "/\\.ubjson/" ) ) settings.encoding = "ubjson";
else if ( uf::string::matched( filename, "/\\.bjdata/" ) ) settings.encoding = "bjdata";
// else UF_MSG_DEBUG( string );
else if ( uf::string::matched( filename, "/\\.toml/" ) ) settings.encoding = "toml";
else if ( uf::string::matched( filename, "/\\.json/" ) ) settings.encoding = "json";
else UF_MSG_DEBUG( "invalid encoding filetype requested: {}", filename );
this->deserialize( buffer, settings );
#if UF_SERIALIZER_AUTO_CONVERT
if ( uf::string::matched( filename, "/\\.json$/" ) ) {
if ( ext::json::PREFERRED_ENCODING != "toml" ) {
uf::stl::string _filename = uf::string::replace( filename, "/\\.json$/", ".toml" );
ext::json::EncodingSettings _settings{
.encoding = "toml",
.compression = "",
};
bool should = !uf::io::exists( _filename ); // auto convert if preferred file doesn't already exist
if ( !should ) should = uf::io::mtime( _filename ) < uf::io::mtime( filename ); // auto convert if preferred file is older than source file
if ( should ) {
writeToFile( _filename, _settings );
}
}
}
if ( uf::string::matched( filename, "/\\.(json|toml)$/" ) ) {
// auto convert read JSON file to TOML
// auto convert read file to preferred filetype
if ( ext::json::PREFERRED_COMPRESSION != "" || (ext::json::PREFERRED_ENCODING != "" || ext::json::PREFERRED_ENCODING != "json") ) {
ext::json::EncodingSettings _settings;
_settings.encoding = ext::json::PREFERRED_ENCODING;
@ -122,7 +155,7 @@ bool uf::Serializer::writeToFile( const uf::stl::string& filename, const ext::js
output += "." + settings.compression;
uf::stl::string buffer = this->serialize( settings );
size_t written = uf::io::write( output, buffer.c_str(), buffer.size() );
size_t written = uf::io::write( output, buffer.data(), buffer.size() );
#if UF_SERIALIZER_AUTO_CONVERT
// implicitly check for optimal format for plain .json requests
if ( uf::string::matched( output, "/\\.json$/" ) && settings.compression != ext::json::PREFERRED_COMPRESSION ) {

View File

@ -62,9 +62,7 @@ void ext::CraetureBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::CraetureBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::CraetureBehavior::tick( uf::Object& self ) {}
void ext::CraetureBehavior::render( uf::Object& self ){}

View File

@ -99,9 +99,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
uf::renderer::addRenderMode( &renderMode, name );
}
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::LightBehavior::tick( uf::Object& self ) {
#if !UF_ENV_DREAMCAST
@ -248,29 +246,30 @@ void ext::LightBehavior::Metadata::serialize( uf::Object& self, uf::Serializer&
serializer["light"]["shadows"] = /*this->*/shadows;
serializer["system"]["renderer"]["mode"] = /*this->*/renderer.mode;
serializer["light"]["external update"] = /*this->*/renderer.external;
serializer["system"]["renderer"]["timer"] = /*this->*/renderer.limiter;
// serializer["system"]["renderer"]["timer"] = /*this->*/renderer.limiter;
switch ( /*this->*/type ) {
case 0: serializer["light"]["type"] = "point"; break;
case 1: serializer["light"]["type"] = "spot"; break;
case 1: serializer["light"]["type"] = "point"; break;
case 2: serializer["light"]["type"] = "spot"; break;
}
}
void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){
/*this->*/color = uf::vector::decode( serializer["light"]["color"], pod::Vector3f{1,1,1} );
/*this->*/power = serializer["light"]["power"].as<float>();
/*this->*/bias = serializer["light"]["bias"]["shader"].as<float>();
/*this->*/shadows = serializer["light"]["shadows"].as<bool>();
/*this->*/renderer.mode = serializer["system"]["renderer"]["mode"].as<uf::stl::string>();
/*this->*/renderer.rendered = false;
/*this->*/renderer.external = serializer["light"]["external update"].as<bool>();
/*this->*/renderer.limiter = serializer["system"]["renderer"]["timer"].as<float>();
/*this->*/color = uf::vector::decode( serializer["light"]["color"], /*this->*/color );
/*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->*/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);
// /*this->*/renderer.limiter = serializer["system"]["renderer"]["timer"].as<float>(/*this->*/renderer.limiter);
if ( serializer["light"]["type"].is<size_t>() ) {
/*this->*/type = serializer["light"]["type"].as<size_t>();
/*this->*/type = serializer["light"]["type"].as<size_t>(/*this->*/type);
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
} else if ( serializer["light"]["type"].is<uf::stl::string>() ) {
uf::stl::string lightType = serializer["light"]["type"].as<uf::stl::string>();
if ( lightType == "point" ) /*this->*/type = 1;
else if ( lightType == "spot" ) /*this->*/type = 2;
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
}
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
}
#undef this

View File

@ -107,9 +107,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
this->queueHook("discord.Activity.Update.%UID%", ext::json::null(), 1.0);
#endif
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::PlayerBehavior::tick( uf::Object& self ) {
auto& camera = this->getComponent<uf::Camera>();
@ -132,6 +130,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
bool jump = false;
bool crouch = false;
bool paused = false;
bool console = false;
bool vee = false;
bool use = false;
} keys;
@ -149,6 +148,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
.jump = uf::inputs::kbm::states::Space,
.crouch = uf::inputs::kbm::states::LControl,
.paused = uf::inputs::kbm::states::Escape,
.console = uf::inputs::kbm::states::Tilde,
.vee = uf::inputs::kbm::states::V,
.use = uf::inputs::kbm::states::E,
};
@ -205,24 +205,28 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
auto& collider = this->getComponent<pod::PhysicsState>();
{
float t = -1;
uf::Object* hit = NULL;
pod::Vector3f center = transform.position + metadata.movement.floored.feet;
pod::Vector3f direction = metadata.movement.floored.floor;
float t = 0.0f;
if ( !stats.floored && collider.body && (t = uf::physics::impl::rayCast( center, direction, this, hit )) >= 0.0f ) {
if ( !stats.floored && collider.body && (hit = uf::physics::impl::rayCast( collider, center, direction, t )) ) {
if ( metadata.movement.floored.print ) UF_MSG_DEBUG("Floored: {} | {}", hit->getName(), t);
stats.floored = true;
}
}
#if 0
TIMER(0.25, keys.use && ) {
size_t uid = 0;
float depth = -1;
uf::Object* pointer = NULL;
float length = metadata.use.length;
pod::Vector3f center = transform.position + cameraTransform.position;
pod::Vector3f direction = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length;
// pod::Vector3f center = transform.position + cameraTransform.position;
// pod::Vector3f direction = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length;
auto flattened = uf::transform::flatten( cameraTransform );
pod::Vector3f center = flattened.position;
pod::Vector3f direction = flattened.forward * length;
float depth = uf::physics::impl::rayCast( center, direction, this, pointer );
pointer = uf::physics::impl::rayCast( center, direction, this, depth );
ext::json::Value payload;
if ( pointer ) {
payload["user"] = this->getUid();
@ -235,7 +239,6 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
payload["depth"] = -1;
}
this->callHook( "entity:Use.%UID%", payload );
/*
auto& emitter = this->getComponent<uf::MappedSoundEmitter>();
uf::stl::string filename = pointer ? "./ui/select.ogg" : "./ui/deny.ogg";
@ -254,6 +257,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
}
*/
}
#endif
if ( collider.stats.gravity == pod::Vector3f{0,0,0} ) stats.noclipped = true;

View File

@ -27,9 +27,7 @@ void ext::PlayerModelBehavior::initialize( uf::Object& self ) {
// transform.reference = &controllerTransform;
// metadata.reference = &controllerTransform;
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::PlayerModelBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<ext::PlayerModelBehavior::Metadata>();

View File

@ -37,9 +37,7 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
uf::renderer::addRenderMode( renderMode, "Compute" );
}
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
@ -115,6 +113,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
@ -141,6 +140,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
metadata.renderer.bound = true;
}
/*
if ( graphic.material.hasShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt) ) {
auto& shader = graphic.material.getShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
@ -149,6 +149,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
auto& shader = graphic.material.getShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt);
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
}
*/
graphic.process = false;
}

View File

@ -113,9 +113,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
if ( !payload.transform.reference ) transform.reference = payload.transform.reference;
});
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
// lock control
{

View File

@ -40,9 +40,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
} );
}
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
// initialize voxel map
#if 0

View File

@ -487,9 +487,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::GuiBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::IMAGE ) ) return;
@ -642,9 +640,12 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
metadataJson["text settings"][key] = value;
});
auto& metadataGlyph = this->getComponent<ext::GuiBehavior::GlyphMetadata>();
// UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadataGlyph, metadataJson);
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
this->addHook( "object:Serialize.%UID%", [&](){ metadataGlyph.serialize(self, metadataJson); });
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadataGlyph.serialize(self, (uf::Serializer&) json); });
this->addHook( "object:Deserialize.%UID%", [&](){ metadataGlyph.deserialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadataGlyph.deserialize(self, (uf::Serializer&) json); });
// metadataGlyph.deserialize(self, metadataJson);
this->addHook( "object:Reload.%UID%", [&](ext::json::Value& json){

View File

@ -84,9 +84,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
}
});
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson);
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
void ext::GuiManagerBehavior::tick( uf::Object& self ) {
#if UF_USE_VULKAN