repaired VR support (to-do: make the VR rendermode work)
This commit is contained in:
parent
e0fbed4a14
commit
a98298b668
@ -116,7 +116,7 @@
|
||||
"deferred": true,
|
||||
"gui": true,
|
||||
"vsync": true, // vsync on vulkan side rather than engine-side
|
||||
"hdr": true,
|
||||
"hdr": false,
|
||||
"vxgi": false, // to-do: fix issues
|
||||
"culling": false,
|
||||
"bloom": true,
|
||||
@ -324,7 +324,7 @@
|
||||
"preset": "native" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x)
|
||||
},
|
||||
"vr" : {
|
||||
"enable" : false,
|
||||
"enable" : true,
|
||||
"manifest": "./data/openvr_manifest.json",
|
||||
"swap eyes": false,
|
||||
"dominant eye": 0,
|
||||
@ -357,7 +357,7 @@
|
||||
"max": 0.1 // 0.2
|
||||
},
|
||||
"debug draw": {
|
||||
"static": false,
|
||||
"static": true,
|
||||
"dynamic": true,
|
||||
"trigger": false,
|
||||
"contacts": false,
|
||||
|
||||
27
bin/data/shaders/display/vr/flat.frag.glsl
Normal file
27
bin/data/shaders/display/vr/flat.frag.glsl
Normal file
@ -0,0 +1,27 @@
|
||||
#version 450
|
||||
#pragma shader_stage(fragment)
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) flat in uint inPass;
|
||||
|
||||
layout (location = 0) out vec4 outLeft;
|
||||
layout (location = 1) out vec4 outRight;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samplerColor;
|
||||
|
||||
layout(constant_id = 0) const int FORCE_OPAQUE = 0;
|
||||
|
||||
#define TEXTURES 1
|
||||
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
#include "../../common/functions.h"
|
||||
|
||||
void main() {
|
||||
vec4 outColor = texture( samplerColor, inUv );
|
||||
if ( FORCE_OPAQUE == 1 ) outColor.a = 1;
|
||||
|
||||
if ( inPass == 0 ) outLeft = outColor;
|
||||
else if ( inPass == 1 ) outRight = outColor;
|
||||
}
|
||||
23
bin/data/shaders/display/vr/flat.vert.glsl
Normal file
23
bin/data/shaders/display/vr/flat.vert.glsl
Normal file
@ -0,0 +1,23 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out flat uint outPass;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 0) uniform Camera {
|
||||
Viewport viewport[6];
|
||||
} camera;
|
||||
|
||||
void main() {
|
||||
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
outPass = PushConstant.pass;
|
||||
gl_Position = camera.viewport[PushConstant.pass].projection * camera.viewport[PushConstant.pass].view * vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
27
bin/data/shaders/display/vr/stereo.frag.glsl
Normal file
27
bin/data/shaders/display/vr/stereo.frag.glsl
Normal file
@ -0,0 +1,27 @@
|
||||
#version 450
|
||||
#pragma shader_stage(fragment)
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) flat in uint inPass;
|
||||
|
||||
layout (location = 0) out vec4 outLeft;
|
||||
layout (location = 1) out vec4 outRight;
|
||||
|
||||
layout (binding = 0) uniform sampler2DArray samplerColor;
|
||||
|
||||
layout(constant_id = 0) const int FORCE_OPAQUE = 0;
|
||||
|
||||
#define TEXTURES 1
|
||||
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
#include "../../common/functions.h"
|
||||
|
||||
void main() {
|
||||
vec4 outColor = texture( samplerColor, vec3(inUv, inPass) );
|
||||
if ( FORCE_OPAQUE == 1 ) outColor.a = 1;
|
||||
|
||||
if ( inPass == 0 ) outLeft = outColor;
|
||||
else if ( inPass == 1 ) outRight = outColor;
|
||||
}
|
||||
16
bin/data/shaders/display/vr/stereo.vert.glsl
Normal file
16
bin/data/shaders/display/vr/stereo.vert.glsl
Normal file
@ -0,0 +1,16 @@
|
||||
#version 450
|
||||
#pragma shader_stage(vertex)
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out flat uint outPass;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
void main() {
|
||||
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
outPass = PushConstant.pass;
|
||||
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
@ -11,6 +11,8 @@
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/utils/window/payloads.h>
|
||||
|
||||
#include <uf/ext/openvr/openvr.h> // yuck
|
||||
|
||||
bool client::ready = false;
|
||||
bool client::terminated = false;
|
||||
uf::Window client::window;
|
||||
@ -110,6 +112,9 @@ void client::initialize() {
|
||||
#else
|
||||
auto& configRenderJson = client::config["engine"]["ext"]["software"];
|
||||
#endif
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::enabled ) return;
|
||||
#endif
|
||||
|
||||
if ( !ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
|
||||
uf::renderer::settings::width = payload.window.size.x;
|
||||
|
||||
@ -24,27 +24,13 @@ namespace vr {
|
||||
|
||||
namespace ext {
|
||||
namespace openvr {
|
||||
struct Driver {
|
||||
uf::stl::string name;
|
||||
uf::stl::string serial;
|
||||
uf::stl::string manifest;
|
||||
vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];
|
||||
uf::stl::string types[vr::k_unMaxTrackedDeviceCount];
|
||||
vr::IVRRenderModels* renderModels;
|
||||
};
|
||||
extern UF_API Driver driver;
|
||||
extern UF_API vr::IVRSystem* context;
|
||||
extern UF_API uint8_t renderPass;
|
||||
extern UF_API float width, height;
|
||||
extern UF_API bool enabled;
|
||||
extern UF_API bool swapEyes;
|
||||
extern UF_API uint8_t dominantEye;
|
||||
|
||||
bool UF_API initialize( int stage = 0 );
|
||||
bool UF_API initialize();
|
||||
void UF_API tick();
|
||||
void UF_API terminate();
|
||||
void UF_API submit();
|
||||
void UF_API synchronize( bool async = true );
|
||||
void UF_API synchronize();
|
||||
float UF_API predictedTimeToDisplay( float additional = 1 );
|
||||
float UF_API updateTracking( float additional = 1 );
|
||||
void UF_API recommendedResolution( uint32_t& width, uint32_t& height );
|
||||
@ -71,8 +57,10 @@ namespace ext {
|
||||
bool UF_API controllerActive( vr::Controller_Hand );
|
||||
|
||||
bool UF_API requestRenderModel( const uf::stl::string& );
|
||||
uf::Graphic& UF_API getRenderModel( const uf::stl::string& );
|
||||
uf::Graphic& UF_API controllerRenderModel( vr::Controller_Hand );
|
||||
uf::Mesh& UF_API getRenderModel( const uf::stl::string& );
|
||||
uf::Mesh& UF_API controllerRenderModel( vr::Controller_Hand );
|
||||
uf::Image& UF_API getRenderTexture( const uf::stl::string& );
|
||||
uf::Image& UF_API controllerRenderTexture( vr::Controller_Hand );
|
||||
|
||||
void UF_API resetPosition();
|
||||
/*
|
||||
|
||||
18
engine/inc/uf/ext/vulkan/rendermodes/vr.h
Normal file
18
engine/inc/uf/ext/vulkan/rendermodes/vr.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/ext/vulkan/rendermode.h>
|
||||
|
||||
namespace ext {
|
||||
namespace vulkan {
|
||||
struct UF_API VrRenderMode : public ext::vulkan::RenderMode {
|
||||
virtual const uf::stl::string getType() const;
|
||||
|
||||
virtual void createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics );
|
||||
virtual void initialize( Device& device );
|
||||
virtual void build( bool = true );
|
||||
virtual void tick();
|
||||
virtual void destroy();
|
||||
virtual void render();
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ namespace ext {
|
||||
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint8_t layers = 0;
|
||||
} descriptor;
|
||||
|
||||
VkImage image;
|
||||
|
||||
@ -486,27 +486,27 @@ pod::Matrix4t<T> /*UF_API*/ uf::matrix::orthographic( T l, T r, T b, T t ) {
|
||||
}
|
||||
template<typename T>
|
||||
pod::Matrix4t<T> /*UF_API*/ uf::matrix::perspective( T fov, T raidou, T znear, T zfar ) {
|
||||
pod::Matrix4t<T> m = uf::matrix::identity<T>();
|
||||
pod::Matrix4t<T> m = uf::matrix::identity<T>();
|
||||
|
||||
T f = static_cast<T>(1) / tan(static_cast<T>(0.5) * fov);
|
||||
m(0,0) = f / raidou;
|
||||
m(1,1) = f;
|
||||
m(0,0) = f / raidou;
|
||||
m(1,1) = f;
|
||||
#if UF_USE_VULKAN
|
||||
m(1,1) = -f;
|
||||
m(1,1) = -f;
|
||||
#endif
|
||||
m(3,2) = 1;
|
||||
m(3,3) = 0;
|
||||
m(3,2) = 1;
|
||||
m(3,3) = 0;
|
||||
|
||||
if ( zfar <= 0 ) {
|
||||
m(2,2) = 0;
|
||||
m(2,3) = znear;
|
||||
} else {
|
||||
T range = zfar - znear;
|
||||
m(2,2) = zfar / range;
|
||||
m(2,3) = -(zfar * znear) / range;
|
||||
}
|
||||
if ( zfar <= 0 ) {
|
||||
m(2,2) = 0;
|
||||
m(2,3) = znear;
|
||||
} else {
|
||||
T range = zfar - znear;
|
||||
m(2,2) = zfar / range;
|
||||
m(2,3) = -(zfar * znear) / range;
|
||||
}
|
||||
|
||||
return m;
|
||||
return m;
|
||||
}
|
||||
template<typename T> T& uf::matrix::copy( T& destination, const T& source ) {
|
||||
FOR_EACH(T::rows * T::columns, {
|
||||
|
||||
@ -48,6 +48,10 @@
|
||||
#include <uf/ext/vall_e/vall_e.h>
|
||||
#include <uf/ext/valve/vpk.h>
|
||||
|
||||
#if UF_USE_OPENVR
|
||||
#include <uf/ext/vulkan/rendermodes/vr.h>
|
||||
#endif
|
||||
|
||||
bool uf::ready = false;
|
||||
uf::stl::vector<uf::stl::string> uf::arguments;
|
||||
uf::Serializer uf::config;
|
||||
@ -112,15 +116,47 @@ void UF_API uf::load() {
|
||||
uf::config.readFromFile(uf::io::root+"config.json");
|
||||
}
|
||||
void UF_API uf::load( ext::json::Value& json ) {
|
||||
auto& configWindowJson = json["window"];
|
||||
auto& configEngineJson = json["engine"];
|
||||
|
||||
auto& configEngineExtJson = configEngineJson["ext"];
|
||||
auto& configEngineSceneJson = configEngineJson["scenes"];
|
||||
auto& configEngineGraphJson = configEngineJson["graph"];
|
||||
auto& configEngineDebugJson = configEngineJson["debug"];
|
||||
auto& configEngineAudioJson = configEngineJson["audio"];
|
||||
auto& configEngineLimitersJson = configEngineJson["limiters"];
|
||||
auto& configEngineThreadJson = configEngineJson["threads"];
|
||||
auto& configEnginePhysicsJson = configEngineJson["physics"];
|
||||
auto& configEnginePhysicsSolverJson = configEnginePhysicsJson["solvers"];
|
||||
auto& configEnginePhysicsCorrectionJson = configEnginePhysicsJson["correction"];
|
||||
auto& configEnginePhysicsDebugDrawJson = configEnginePhysicsJson["debug draw"];
|
||||
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
|
||||
auto& configEngineExtFfxJson = configEngineExtJson["fsr"];
|
||||
#endif
|
||||
#if UF_USE_VALL_E
|
||||
auto& configEngineExtValleJson = configEngineExtJson["vall_e"];
|
||||
#endif
|
||||
#if UF_USE_ULTRALIGHT
|
||||
auto& configEngineExtUltralightJson = configEngineExtJson["ultralight"];
|
||||
#endif
|
||||
#if UF_USE_VULKAN
|
||||
auto& configRenderJson = configEngineExtJson["vulkan"];
|
||||
#elif UF_USE_OPENGL
|
||||
auto& configRenderJson = configEngineExtJson["opengl"];
|
||||
#else
|
||||
auto& configRenderJson = configEngineExtJson["software"];
|
||||
#endif
|
||||
auto& configRenderInvariantJson = configRenderJson["invariant"];
|
||||
auto& configRenderExperimentalJson = configRenderJson["experimental"];
|
||||
auto& configRenderPipelinesJson = configRenderJson["pipelines"];
|
||||
|
||||
// Scene settings
|
||||
{
|
||||
auto& configEngineSceneJson = json["engine"]["scenes"];
|
||||
uf::matrix::reverseInfiniteProjection = configEngineSceneJson["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection );
|
||||
}
|
||||
|
||||
// Graph settings
|
||||
{
|
||||
auto& configEngineGraphJson = json["engine"]["graph"];
|
||||
uf::graph::initialBufferElements = configEngineGraphJson["initial buffer elements"].as(uf::graph::initialBufferElements);
|
||||
if ( configEngineGraphJson["storage mode"].is<uf::stl::string>() ) {
|
||||
auto mode = uf::string::lowercase( configEngineGraphJson["storage mode"].as<uf::stl::string>() );
|
||||
@ -135,15 +171,14 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
// Various debug settings
|
||||
{
|
||||
auto& configEngineDebugJson = json["engine"]["debug"];
|
||||
/*global*/::config.engine.gc.enabled = configEngineDebugJson["garbage collection"]["enabled"].as(/*global*/::config.engine.gc.enabled);
|
||||
/*global*/::config.engine.gc.every = configEngineDebugJson["garbage collection"]["every"].as(/*global*/::config.engine.gc.every);
|
||||
/*global*/::config.engine.gc.mode = configEngineDebugJson["garbage collection"]["mode"].as(/*global*/::config.engine.gc.mode);
|
||||
/*global*/::config.engine.gc.announce = configEngineDebugJson["garbage collection"]["announce"].as(/*global*/::config.engine.gc.announce);
|
||||
::config.engine.gc.enabled = configEngineDebugJson["garbage collection"]["enabled"].as(::config.engine.gc.enabled);
|
||||
::config.engine.gc.every = configEngineDebugJson["garbage collection"]["every"].as(::config.engine.gc.every);
|
||||
::config.engine.gc.mode = configEngineDebugJson["garbage collection"]["mode"].as(::config.engine.gc.mode);
|
||||
::config.engine.gc.announce = configEngineDebugJson["garbage collection"]["announce"].as(::config.engine.gc.announce);
|
||||
|
||||
/*global*/::config.engine.limiter.print = configEngineDebugJson["framerate"]["print"].as(/*global*/::config.engine.limiter.print);
|
||||
/*global*/::config.engine.fps.print = configEngineDebugJson["framerate"]["print"].as(/*global*/::config.engine.fps.print);
|
||||
/*global*/::config.engine.fps.every = configEngineDebugJson["framerate"]["every"].as(/*global*/::config.engine.fps.every);
|
||||
::config.engine.limiter.print = configEngineDebugJson["framerate"]["print"].as(::config.engine.limiter.print);
|
||||
::config.engine.fps.print = configEngineDebugJson["framerate"]["print"].as(::config.engine.fps.print);
|
||||
::config.engine.fps.every = configEngineDebugJson["framerate"]["every"].as(::config.engine.fps.every);
|
||||
|
||||
uf::Entity::deleteChildrenOnDestroy = configEngineDebugJson["entity"]["delete children on destroy"].as( uf::Entity::deleteChildrenOnDestroy );
|
||||
uf::Entity::deleteComponentsOnDestroy = configEngineDebugJson["entity"]["delete components on destroy"].as( uf::Entity::deleteComponentsOnDestroy );
|
||||
@ -160,18 +195,17 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
}
|
||||
// Limiter settings
|
||||
{
|
||||
auto& configEngineLimitersJson = json["engine"]["limiters"];
|
||||
if ( configEngineLimitersJson["framerate"].as<uf::stl::string>() == "auto" && json["window"]["refresh rate"].is<size_t>() ) {
|
||||
if ( configEngineLimitersJson["framerate"].as<uf::stl::string>() == "auto" && configWindowJson["refresh rate"].is<size_t>() ) {
|
||||
float scale = 1.0;
|
||||
size_t refreshRate = json["window"]["refresh rate"].as<size_t>();
|
||||
size_t refreshRate = configWindowJson["refresh rate"].as<size_t>();
|
||||
configEngineLimitersJson["framerate"] = refreshRate * scale;
|
||||
UF_MSG_DEBUG("Setting framerate cap to {}", (int) refreshRate * scale);
|
||||
}
|
||||
|
||||
/* Frame limiter */ {
|
||||
size_t limit = configEngineLimitersJson["framerate"].as<size_t>();
|
||||
/*global*/::times.limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
UF_MSG_DEBUG("Limiter set to {} ms", /*global*/::times.limiter);
|
||||
::times.limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
UF_MSG_DEBUG("Limiter set to {} ms", ::times.limiter);
|
||||
}
|
||||
/* Max delta time */{
|
||||
size_t limit = configEngineLimitersJson["deltaTime"].as<size_t>();
|
||||
@ -181,10 +215,9 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
// Thread settings
|
||||
{
|
||||
auto& configEngineThreadJson = json["engine"]["threads"];
|
||||
if ( configEngineThreadJson["frame limiter"].as<uf::stl::string>() == "auto" && json["window"]["refresh rate"].is<size_t>() ) {
|
||||
if ( configEngineThreadJson["frame limiter"].as<uf::stl::string>() == "auto" && configWindowJson["refresh rate"].is<size_t>() ) {
|
||||
float scale = 2.0;
|
||||
size_t refreshRate = json["window"]["refresh rate"].as<size_t>();
|
||||
size_t refreshRate = configWindowJson["refresh rate"].as<size_t>();
|
||||
configEngineThreadJson["frame limiter"] = refreshRate * scale;
|
||||
UF_MSG_DEBUG("Setting thread frame limiter to {}", (int) refreshRate * scale);
|
||||
}
|
||||
@ -209,14 +242,12 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
// Physics settings
|
||||
{
|
||||
auto& configEnginePhysicsJson = json["engine"]["physics"];
|
||||
uf::physics::settings.async = configEnginePhysicsJson["async"].as(uf::physics::settings.async);
|
||||
uf::physics::settings.timestep = configEnginePhysicsJson["timestep"].as(uf::physics::settings.timestep);
|
||||
uf::physics::settings.fixedStep = configEnginePhysicsJson["fixed step"].as(uf::physics::settings.fixedStep);
|
||||
uf::physics::settings.substeps = configEnginePhysicsJson["substeps"].as(uf::physics::settings.substeps);
|
||||
uf::physics::settings.flattenTransforms = configEnginePhysicsJson["flatten transforms"].as(uf::physics::settings.flattenTransforms);
|
||||
|
||||
auto& configEnginePhysicsSolverJson = configEnginePhysicsJson["solvers"];
|
||||
if ( ext::json::isObject( configEnginePhysicsSolverJson ) ) {
|
||||
uf::physics::settings.useGjk = configEnginePhysicsSolverJson["gjk"].as(uf::physics::settings.useGjk);
|
||||
uf::physics::settings.blockContactSolver = configEnginePhysicsSolverJson["block"].as(uf::physics::settings.blockContactSolver);
|
||||
@ -224,14 +255,12 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
uf::physics::settings.resolveBlockContact = configEnginePhysicsSolverJson["resolve invalid"].as(uf::physics::settings.resolveBlockContact);
|
||||
uf::physics::settings.solverIterations = configEnginePhysicsSolverJson["iterations"].as(uf::physics::settings.solverIterations);
|
||||
}
|
||||
auto& configEnginePhysicsCorrectionJson = configEnginePhysicsJson["correction"];
|
||||
if ( ext::json::isObject( configEnginePhysicsCorrectionJson ) ) {
|
||||
uf::physics::settings.ngsPositionSolver = configEnginePhysicsCorrectionJson["ngs"].as(uf::physics::settings.ngsPositionSolver);
|
||||
uf::physics::settings.baumgarteCorrectionPercent = configEnginePhysicsCorrectionJson["percent"].as(uf::physics::settings.baumgarteCorrectionPercent);
|
||||
uf::physics::settings.baumgarteCorrectionSlop = configEnginePhysicsCorrectionJson["slop"].as(uf::physics::settings.baumgarteCorrectionSlop);
|
||||
uf::physics::settings.maxLinearCorrection = configEnginePhysicsCorrectionJson["max"].as(uf::physics::settings.maxLinearCorrection);
|
||||
}
|
||||
auto& configEnginePhysicsDebugDrawJson = configEnginePhysicsJson["debug draw"];
|
||||
if ( ext::json::isObject( configEnginePhysicsDebugDrawJson ) ) {
|
||||
if ( configEnginePhysicsDebugDrawJson["static"].as<bool>() ) uf::physics::settings.debugDraw.mask |= pod::Collider::CATEGORY_STATIC;
|
||||
if ( configEnginePhysicsDebugDrawJson["dynamic"].as<bool>() ) uf::physics::settings.debugDraw.mask |= pod::Collider::CATEGORY_DYNAMIC;
|
||||
@ -257,7 +286,6 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
// Audio settings
|
||||
{
|
||||
auto& configEngineAudioJson = json["engine"]["audio"];
|
||||
uf::audio::muted = configEngineAudioJson["mute"].as( uf::audio::muted );
|
||||
uf::audio::asyncUpdate = configEngineAudioJson["async update"].as( uf::audio::asyncUpdate );
|
||||
uf::audio::streamsByDefault = configEngineAudioJson["streams by default"].as( uf::audio::streamsByDefault );
|
||||
@ -278,23 +306,29 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
}
|
||||
|
||||
// Various external settings
|
||||
#if UF_USE_DISCORD
|
||||
{
|
||||
/*global*/::config.engine.ext.discord.enabled = json["engine"]["ext"]["discord"]["enabled"].as(/*global*/::config.engine.ext.discord.enabled);
|
||||
/*global*/::config.engine.ext.imgui.enabled = json["engine"]["ext"]["imgui"]["enabled"].as(/*global*/::config.engine.ext.imgui.enabled);
|
||||
::config.engine.ext.discord.enabled = configEngineExtJson["discord"]["enabled"].as(::config.engine.ext.discord.enabled);
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_IMGUI
|
||||
{
|
||||
::config.engine.ext.imgui.enabled = configEngineExtJson["imgui"]["enabled"].as(::config.engine.ext.imgui.enabled);
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_VALL_E
|
||||
// VALL-E settings
|
||||
{
|
||||
auto& configEngineExtValleJson = json["engine"]["ext"]["vall_e"];
|
||||
/*global*/::config.engine.ext.vall_e.enabled = configEngineExtValleJson["enabled"].as(/*global*/::config.engine.ext.vall_e.enabled);
|
||||
/*global*/::config.engine.ext.vall_e.model_path = configEngineExtValleJson["model_path"].as(/*global*/::config.engine.ext.vall_e.model_path);
|
||||
/*global*/::config.engine.ext.vall_e.encodec_path = configEngineExtValleJson["encodec_path"].as(/*global*/::config.engine.ext.vall_e.encodec_path);
|
||||
::config.engine.ext.vall_e.enabled = configEngineExtValleJson["enabled"].as(::config.engine.ext.vall_e.enabled);
|
||||
::config.engine.ext.vall_e.model_path = configEngineExtValleJson["model_path"].as(::config.engine.ext.vall_e.model_path);
|
||||
::config.engine.ext.vall_e.encodec_path = configEngineExtValleJson["encodec_path"].as(::config.engine.ext.vall_e.encodec_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UF_USE_ULTRALIGHT
|
||||
// Ultralight settings (painfully unused)
|
||||
{
|
||||
auto& configEngineExtUltralightJson = json["engine"]["ext"]["ultralight"];
|
||||
/*global*/::config.engine.ext.ultralight.enabled = configEngineExtUltralightJson["enabled"].as(/*global*/::config.engine.ext.ultralight.enabled);
|
||||
::config.engine.ext.ultralight.enabled = configEngineExtUltralightJson["enabled"].as(::config.engine.ext.ultralight.enabled);
|
||||
ext::ultralight::scale = configEngineExtUltralightJson["scale"].as( ext::ultralight::scale );
|
||||
ext::ultralight::log = configEngineExtUltralightJson["log"].as( ext::ultralight::log );
|
||||
}
|
||||
@ -302,17 +336,6 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
|
||||
// Renderer settings
|
||||
{
|
||||
#if UF_USE_VULKAN
|
||||
auto& configRenderJson = json["engine"]["ext"]["vulkan"];
|
||||
#elif UF_USE_OPENGL
|
||||
auto& configRenderJson = json["engine"]["ext"]["opengl"];
|
||||
#else
|
||||
auto& configRenderJson = json["engine"]["ext"]["software"];
|
||||
#endif
|
||||
auto& configRenderInvariantJson = configRenderJson["invariant"];
|
||||
auto& configRenderExperimentalJson = configRenderJson["experimental"];
|
||||
auto& configRenderPipelinesJson = configRenderJson["pipelines"];
|
||||
|
||||
uf::renderer::settings::validation::messages = configRenderJson["validation"]["messages"].as( uf::renderer::settings::validation::messages );
|
||||
uf::renderer::settings::validation::checkpoints = configRenderJson["validation"]["checkpoints"].as( uf::renderer::settings::validation::checkpoints );
|
||||
|
||||
@ -323,7 +346,7 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
uf::renderer::settings::defaultDeferBufferDestroy = configRenderInvariantJson["default defer buffer destroy"].as( uf::renderer::settings::defaultDeferBufferDestroy );
|
||||
#if 0
|
||||
uf::renderer::settings::defaultCommandBufferImmediate = true;
|
||||
/*global*/::requestDeferredCommandBufferSubmit = !configRenderInvariantJson["default command buffer immediate"].as( uf::renderer::settings::defaultCommandBufferImmediate );
|
||||
::requestDeferredCommandBufferSubmit = !configRenderInvariantJson["default command buffer immediate"].as( uf::renderer::settings::defaultCommandBufferImmediate );
|
||||
#else
|
||||
uf::renderer::settings::defaultCommandBufferImmediate = configRenderInvariantJson["default command buffer immediate"].as( uf::renderer::settings::defaultCommandBufferImmediate );
|
||||
#endif
|
||||
@ -331,7 +354,7 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
#endif
|
||||
#if 1
|
||||
uf::renderer::settings::experimental::dedicatedThread = false;
|
||||
/*global*/::requestDedicatedRenderThread = configRenderExperimentalJson["dedicated thread"].as( uf::renderer::settings::experimental::dedicatedThread );
|
||||
::requestDedicatedRenderThread = configRenderExperimentalJson["dedicated thread"].as( uf::renderer::settings::experimental::dedicatedThread );
|
||||
#else
|
||||
uf::renderer::settings::experimental::dedicatedThread = configRenderExperimentalJson["dedicated thread"].as( uf::renderer::settings::experimental::dedicatedThread );
|
||||
#endif
|
||||
@ -340,40 +363,44 @@ void UF_API uf::load( ext::json::Value& json ) {
|
||||
uf::renderer::settings::invariant::individualPipelines = configRenderInvariantJson["individual pipelines"].as( uf::renderer::settings::invariant::individualPipelines );
|
||||
}
|
||||
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
|
||||
ext::fsr::preset = json["engine"]["ext"]["fsr"]["preset"].as(ext::fsr::preset);
|
||||
ext::fsr::jitterScale = json["engine"]["ext"]["fsr"]["jitter scale"].as(ext::fsr::jitterScale);
|
||||
ext::fsr::sharpness = json["engine"]["ext"]["fsr"]["sharpness"].as(ext::fsr::sharpness);
|
||||
ext::fsr::preset = configEngineExtFfxJson["preset"].as(ext::fsr::preset);
|
||||
ext::fsr::jitterScale = configEngineExtFfxJson["jitter scale"].as(ext::fsr::jitterScale);
|
||||
ext::fsr::sharpness = configEngineExtFfxJson["sharpness"].as(ext::fsr::sharpness);
|
||||
|
||||
ext::fsr::frameUpscale = json["engine"]["ext"]["fsr"]["upscale"].as(ext::fsr::frameUpscale);
|
||||
ext::fsr::frameInterpolation = json["engine"]["ext"]["fsr"]["interpolation"].as(ext::fsr::frameInterpolation);
|
||||
ext::fsr::frameUpscale = configEngineExtFfxJson["upscale"].as(ext::fsr::frameUpscale);
|
||||
ext::fsr::frameInterpolation = configEngineExtFfxJson["interpolation"].as(ext::fsr::frameInterpolation);
|
||||
|
||||
{
|
||||
bool enabled = json["engine"]["ext"]["fsr"]["enabled"].as(true);
|
||||
if ( !enabled ) {
|
||||
ext::fsr::frameUpscale = false;
|
||||
ext::fsr::frameInterpolation = false;
|
||||
}
|
||||
if ( !configEngineExtFfxJson["enabled"].as(true) ) {
|
||||
ext::fsr::frameUpscale = false;
|
||||
ext::fsr::frameInterpolation = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 && UF_USE_OPENVR
|
||||
static auto* vrRenderMode = new ext::vulkan::VrRenderMode;
|
||||
uf::renderer::addRenderMode(vrRenderMode, "VR");
|
||||
#endif
|
||||
|
||||
// shouldn't ever fire because the deferred rendermode is owned by the scene now
|
||||
if ( uf::renderer::hasRenderMode("", true) ) {
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
|
||||
if ( uf::renderer::settings::pipelines::fsr ) {
|
||||
float factor = 1.0f;
|
||||
auto mode = uf::string::lowercase( ext::fsr::preset );
|
||||
if ( mode == "native" ) renderMode.scale = 1;
|
||||
else if ( mode == "quality" ) renderMode.scale = 1.0f / (1.5f);
|
||||
else if ( mode == "balanced" ) renderMode.scale = 1.0f / (1.7f);
|
||||
else if ( mode == "performance" ) renderMode.scale = 1.0f / (2.0f);
|
||||
else if ( mode == "ultra" ) renderMode.scale = 1.0f / (3.0f);
|
||||
if ( mode == "native" ) factor = 1.0f;
|
||||
else if ( mode == "quality" ) factor = 1.5f;
|
||||
else if ( mode == "balanced" ) factor = 1.7f;
|
||||
else if ( mode == "performance" ) factor = 2.0f;
|
||||
else if ( mode == "ultra" ) factor = 3.0f;
|
||||
else {
|
||||
renderMode.scale = 1;
|
||||
UF_MSG_WARNING("Invalid FFX FSR preset enum string specified: {}", mode);
|
||||
}
|
||||
renderMode.scale = 1.0f / factor;
|
||||
UF_MSG_DEBUG("Using FFX FSR Preset: {} ({:.3f}% render scale)", mode, (100.0f / renderMode.scale));
|
||||
} else
|
||||
#endif
|
||||
renderMode.scale = uf::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(1.0f);
|
||||
renderMode.scale = configRenderJson["framebuffer"]["size"].as(1.0f);
|
||||
UF_MSG_DEBUG("Geometry render scale: {:.3f}", renderMode.scale);
|
||||
}
|
||||
}
|
||||
@ -434,11 +461,11 @@ void UF_API uf::initialize() {
|
||||
std::srand(std::time(NULL));
|
||||
}
|
||||
/* Open output file */ {
|
||||
/*global*/::io.filenames.output = uf::io::root+"/logs/output.txt";
|
||||
/*global*/::io.output.open(/*global*/::io.filenames.output);
|
||||
::io.filenames.output = uf::io::root+"/logs/output.txt";
|
||||
::io.output.open(::io.filenames.output);
|
||||
}
|
||||
/* Initialize timers */ {
|
||||
/*global*/::times.sys.start();
|
||||
::times.sys.start();
|
||||
}
|
||||
/* Read persistent data */ {
|
||||
// #include "./inits/persistence.inl"
|
||||
@ -495,6 +522,7 @@ void UF_API uf::initialize() {
|
||||
}
|
||||
uf::allocator::override = configMemoryPoolJson["override"].as( uf::allocator::override );
|
||||
}
|
||||
|
||||
/* Setup commands */ {
|
||||
uf::console::initialize();
|
||||
}
|
||||
@ -507,10 +535,9 @@ void UF_API uf::initialize() {
|
||||
}
|
||||
|
||||
/* Create initial scene (kludge) */ {
|
||||
uf::Scene& scene = uf::instantiator::instantiate<uf::Scene>(); //new uf::Scene;
|
||||
uf::Scene& scene = uf::instantiator::instantiate<uf::Scene>();
|
||||
uf::scene::scenes.emplace_back(&scene);
|
||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||
// metadata["system"]["config"] = uf::config;
|
||||
}
|
||||
|
||||
uf::load( uf::config );
|
||||
@ -539,7 +566,7 @@ void UF_API uf::initialize() {
|
||||
} else if ( ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
|
||||
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>() );
|
||||
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;
|
||||
else if ( filter == "linear" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::LINEAR;
|
||||
@ -607,12 +634,9 @@ void UF_API uf::initialize() {
|
||||
|
||||
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
|
||||
uf::renderer::settings::pipelines::fsr = configRenderPipelinesJson["fsr"].as( uf::renderer::settings::pipelines::fsr );
|
||||
// ext::fsr::enabled = uf::renderer::settings::pipelines::fsr;
|
||||
#endif
|
||||
|
||||
if ( uf::renderer::settings::pipelines::rt ) {
|
||||
// uf::renderer::settings::pipelines::vxgi = false;
|
||||
// uf::renderer::settings::pipelines::culling = false;
|
||||
uf::config["engine"]["scenes"]["lights"]["shadows"]["enabled"] = false;
|
||||
}
|
||||
#define JSON_TO_FORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
|
||||
@ -645,110 +669,13 @@ void UF_API uf::initialize() {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Physics */ {
|
||||
// uf::physics::initialize();
|
||||
}
|
||||
|
||||
#if UF_USE_OPENVR
|
||||
{
|
||||
auto& configVrJson = uf::config["engine"]["ext"]["vr"];
|
||||
|
||||
ext::openvr::enabled = configVrJson["enable"].as( ext::openvr::enabled );
|
||||
ext::openvr::swapEyes = configVrJson["swap eyes"].as( ext::openvr::swapEyes );
|
||||
|
||||
|
||||
if ( configVrJson["dominant eye"].is<int>() ) {
|
||||
ext::openvr::dominantEye = configVrJson["dominant eye"].as<int>();
|
||||
} 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(ext::openvr::driver.manifest);
|
||||
|
||||
if ( ext::openvr::enabled ) uf::config["engine"]["render modes"]["stereo deferred"] = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize Vulkan */ {
|
||||
// to-do: have this set per config value instead of relying on the scene to handle its own rendermodes
|
||||
if ( false ) {
|
||||
// setup render mode
|
||||
if ( uf::config["engine"]["render modes"]["deferred"].as<bool>(true) ) {
|
||||
auto* renderMode = new uf::renderer::DeferredRenderMode;
|
||||
|
||||
if ( uf::config["engine"]["ext"]["vulkan"]["pipelines"]["postProcess"].is<uf::stl::string>() )
|
||||
renderMode->metadata.json["postProcess"] = uf::config["engine"]["ext"]["vulkan"]["pipelines"]["postProcess"];
|
||||
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode->blitter.descriptor.subpass = 0;
|
||||
#if UF_USE_FFX_FSR || UF_USE_FFX_SDK
|
||||
if ( uf::renderer::settings::pipelines::fsr ) {
|
||||
auto mode = uf::string::lowercase( ext::fsr::preset );
|
||||
if ( mode == "native" ) renderMode->scale = 1;
|
||||
else if ( mode == "quality" ) renderMode->scale = 1.0f / (1.5f);
|
||||
else if ( mode == "balanced" ) renderMode->scale = 1.0f / (1.7f);
|
||||
else if ( mode == "performance" ) renderMode->scale = 1.0f / (2.0f);
|
||||
else if ( mode == "ultra" ) renderMode->scale = 1.0f / (3.0f);
|
||||
else {
|
||||
renderMode->scale = 1;
|
||||
UF_MSG_WARNING("Invalid FFX FSR preset enum string specified: {}", mode);
|
||||
}
|
||||
UF_MSG_DEBUG("Using FFX FSR Preset: {} ({:.3f}% render scale)", mode, (100.0f / renderMode->scale));
|
||||
} else
|
||||
#endif
|
||||
renderMode->scale = uf::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(1.0f);
|
||||
UF_MSG_DEBUG("Geometry render scale: {:.3f}", renderMode->scale);
|
||||
|
||||
if ( uf::config["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
|
||||
renderMode->metadata.eyes = 2;
|
||||
}
|
||||
#if UF_USE_VULKAN
|
||||
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);
|
||||
}
|
||||
if ( uf::renderer::settings::pipelines::rt ) {
|
||||
renderMode->metadata.pipelines.emplace_back("skinning");
|
||||
}
|
||||
#endif
|
||||
|
||||
uf::renderer::addRenderMode( renderMode, "" );
|
||||
}
|
||||
|
||||
if ( uf::config["engine"]["render modes"]["gui"].as<bool>(true) ) {
|
||||
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
|
||||
if ( uf::config["engine"]["ext"]["vulkan"]["pipelines"]["postProcess"].is<uf::stl::string>() )
|
||||
renderMode->metadata.json["postProcess"] = uf::config["engine"]["ext"]["vulkan"]["pipelines"]["postProcess"];
|
||||
|
||||
uf::stl::string name = "Gui";
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode->blitter.descriptor.subpass = 0;
|
||||
renderMode->metadata.type = "single";
|
||||
uf::renderer::addRenderMode( renderMode, name );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::enabled ) {
|
||||
ext::openvr::initialize();
|
||||
|
||||
uint32_t width, height;
|
||||
ext::openvr::recommendedResolution( width, height );
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
renderMode.width = width;
|
||||
renderMode.height = height;
|
||||
|
||||
UF_MSG_DEBUG("Recommended VR Resolution: {}, {}", renderMode.width, renderMode.height);
|
||||
|
||||
if ( uf::config["engine"]["ext"]["vr"]["scale"].is<float>() ) {
|
||||
float scale = uf::config["engine"]["ext"]["vr"]["scale"].as<float>();
|
||||
renderMode.width *= scale;
|
||||
renderMode.height *= scale;
|
||||
|
||||
UF_MSG_DEBUG("VR Resolution: {}, {}", renderMode.width, renderMode.height);
|
||||
if ( ext::openvr::enabled && (ext::openvr::enabled = ext::openvr::initialize())) {
|
||||
ext::openvr::recommendedResolution( uf::renderer::settings::width, uf::renderer::settings::height );
|
||||
UF_MSG_DEBUG("VR Resolution: {}, {}", uf::renderer::settings::width, uf::renderer::settings::height);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -770,23 +697,23 @@ void UF_API uf::initialize() {
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_DISCORD
|
||||
/* Discord */ if ( /*global*/::config.engine.ext.discord.enabled ) {
|
||||
/* Discord */ if ( ::config.engine.ext.discord.enabled ) {
|
||||
ext::discord::initialize();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_ULTRALIGHT
|
||||
/* Ultralight-UX */ if ( /*global*/::config.engine.ext.ultralight.enabled ) {
|
||||
/* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
|
||||
ext::ultralight::initialize();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_IMGUI
|
||||
if ( /*global*/::config.engine.ext.imgui.enabled ) {
|
||||
if ( ::config.engine.ext.imgui.enabled ) {
|
||||
// ext::imgui::initialize();
|
||||
}
|
||||
#endif
|
||||
#if 0 && UF_USE_VALL_E
|
||||
if ( /*global*/::config.engine.ext.vall_e.enabled ) {
|
||||
ext::vall_e::initialize( /*global*/::config.engine.ext.vall_e.model_path, /*global*/::config.engine.ext.vall_e.encodec_path );
|
||||
if ( ::config.engine.ext.vall_e.enabled ) {
|
||||
ext::vall_e::initialize( ::config.engine.ext.vall_e.model_path, ::config.engine.ext.vall_e.encodec_path );
|
||||
|
||||
// bind the hook
|
||||
uf::hooks.addHook( "llm:VALL-E.synthesize", [&](ext::json::Value& json){
|
||||
@ -811,8 +738,8 @@ void UF_API uf::initialize() {
|
||||
#endif
|
||||
/* Add hooks */ {
|
||||
uf::hooks.addHook( "game:Scene.Load", [&](ext::json::Value& json){
|
||||
/*global*/::sceneTransition.payload = json;
|
||||
/*global*/::sceneTransition.phase = 0;
|
||||
::sceneTransition.payload = json;
|
||||
::sceneTransition.phase = 0;
|
||||
});
|
||||
uf::hooks.addHook( "system:Quit", [&](ext::json::Value& json){
|
||||
if ( json["message"].is<uf::stl::string>() ) {
|
||||
@ -825,12 +752,12 @@ void UF_API uf::initialize() {
|
||||
/* Initialize root scene*/ {
|
||||
ext::json::Value payload;
|
||||
payload["scene"] = uf::config["engine"]["scenes"]["start"];
|
||||
/*global*/::sceneTransition.payload = payload;
|
||||
/*global*/::sceneTransition.phase = 0;
|
||||
::sceneTransition.payload = payload;
|
||||
::sceneTransition.phase = 0;
|
||||
}
|
||||
|
||||
uf::ready = true;
|
||||
UF_MSG_INFO("EXT took {} seconds to initialize", /*global*/::times.sys.elapsed().asDouble());
|
||||
UF_MSG_INFO("EXT took {} seconds to initialize", ::times.sys.elapsed().asDouble());
|
||||
}
|
||||
|
||||
void UF_API uf::tick() {
|
||||
@ -843,9 +770,9 @@ void UF_API uf::tick() {
|
||||
|
||||
#if 1
|
||||
// skip the next tick to load the next scene to ensure nothing's happening
|
||||
if ( /*global*/::sceneTransition.phase >= 0 ) {
|
||||
auto target = /*global*/::sceneTransition.payload["scene"].as<uf::stl::string>();
|
||||
auto& phase = /*global*/::sceneTransition.phase;
|
||||
if ( ::sceneTransition.phase >= 0 ) {
|
||||
auto target = ::sceneTransition.payload["scene"].as<uf::stl::string>();
|
||||
auto& phase = ::sceneTransition.phase;
|
||||
|
||||
++phase;
|
||||
|
||||
@ -856,12 +783,12 @@ void UF_API uf::tick() {
|
||||
uf::renderer::synchronize();
|
||||
|
||||
if ( uf::renderer::settings::experimental::dedicatedThread ) {
|
||||
/*global*/::requestDedicatedRenderThread = true;
|
||||
::requestDedicatedRenderThread = true;
|
||||
uf::renderer::settings::experimental::dedicatedThread = !uf::renderer::settings::experimental::dedicatedThread;
|
||||
}
|
||||
#if UF_USE_VULKAN
|
||||
if ( !uf::renderer::settings::defaultCommandBufferImmediate ) {
|
||||
/*global*/::requestDeferredCommandBufferSubmit = true;
|
||||
::requestDeferredCommandBufferSubmit = true;
|
||||
uf::renderer::settings::defaultCommandBufferImmediate = !uf::renderer::settings::defaultCommandBufferImmediate;
|
||||
}
|
||||
#endif
|
||||
@ -869,7 +796,7 @@ void UF_API uf::tick() {
|
||||
uf::scene::unloadScene();
|
||||
uf::scene::loadScene( target );
|
||||
|
||||
/*global*/::sceneTransition.phase = -1;
|
||||
::sceneTransition.phase = -1;
|
||||
|
||||
#if UF_USE_VULKAN
|
||||
uf::renderer::flushCommandBuffers();
|
||||
@ -884,7 +811,7 @@ void UF_API uf::tick() {
|
||||
spec::controller::tick();
|
||||
}
|
||||
#if UF_USE_OPENVR
|
||||
/* OpenVR */ if ( ext::openvr::context ) {
|
||||
/* OpenVR */ if ( ext::openvr::enabled ) {
|
||||
ext::openvr::tick();
|
||||
}
|
||||
#endif
|
||||
@ -944,7 +871,7 @@ void UF_API uf::tick() {
|
||||
uf::thread::process( threadMain );
|
||||
}
|
||||
#if UF_USE_ULTRALIGHT
|
||||
/* Ultralight-UX */ if ( /*global*/::config.engine.ext.ultralight.enabled ) {
|
||||
/* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
|
||||
ext::ultralight::tick();
|
||||
}
|
||||
#endif
|
||||
@ -953,22 +880,22 @@ void UF_API uf::tick() {
|
||||
}
|
||||
|
||||
#if UF_USE_DISCORD
|
||||
/* Discord */ if ( /*global*/::config.engine.ext.discord.enabled ) {
|
||||
/* Discord */ if ( ::config.engine.ext.discord.enabled ) {
|
||||
ext::discord::tick();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_IMGUI
|
||||
if ( /*global*/::config.engine.ext.imgui.enabled ) {
|
||||
if ( ::config.engine.ext.imgui.enabled ) {
|
||||
ext::imgui::tick();
|
||||
}
|
||||
#endif
|
||||
|
||||
// perform GC on entities
|
||||
if ( /*global*/::config.engine.gc.enabled ) {
|
||||
TIMER( /*global*/::config.engine.gc.every ) {
|
||||
size_t collected = uf::instantiator::collect( /*global*/::config.engine.gc.mode );
|
||||
if ( ::config.engine.gc.enabled ) {
|
||||
TIMER( ::config.engine.gc.every ) {
|
||||
size_t collected = uf::instantiator::collect( ::config.engine.gc.mode );
|
||||
if ( collected > 0 ) {
|
||||
if ( /*global*/::config.engine.gc.announce ) UF_MSG_DEBUG("GC collected {} unused entities", (int) collected);
|
||||
if ( ::config.engine.gc.announce ) UF_MSG_DEBUG("GC collected {} unused entities", (int) collected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -978,10 +905,10 @@ void UF_API uf::tick() {
|
||||
#endif
|
||||
|
||||
#if !UF_ENV_DREAMCAST
|
||||
if ( /*global*/::times.limiter > 0 ) {
|
||||
if ( ::times.limiter > 0 ) {
|
||||
static auto nextFrameTime = std::chrono::steady_clock::now();
|
||||
|
||||
double limiterMs = /*global*/::times.limiter * 1000.0;
|
||||
double limiterMs = ::times.limiter * 1000.0;
|
||||
auto limiterDuration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::duration<double, std::milli>(limiterMs));
|
||||
nextFrameTime += limiterDuration;
|
||||
|
||||
@ -996,14 +923,14 @@ void UF_API uf::tick() {
|
||||
}
|
||||
|
||||
auto& controller = uf::scene::getCurrentScene().getController();
|
||||
if ( /*global*/::requestDedicatedRenderThread && controller.getName() == "Player" ) {
|
||||
/*global*/::requestDedicatedRenderThread = false;
|
||||
if ( ::requestDedicatedRenderThread && controller.getName() == "Player" ) {
|
||||
::requestDedicatedRenderThread = false;
|
||||
uf::renderer::settings::experimental::dedicatedThread = true;
|
||||
UF_MSG_DEBUG("Dedicated render requested");
|
||||
}
|
||||
#if UF_USE_VULKAN
|
||||
if ( /*global*/::requestDeferredCommandBufferSubmit && controller.getName() == "Player" ) {
|
||||
/*global*/::requestDeferredCommandBufferSubmit = false;
|
||||
if ( ::requestDeferredCommandBufferSubmit && controller.getName() == "Player" ) {
|
||||
::requestDeferredCommandBufferSubmit = false;
|
||||
uf::renderer::settings::defaultCommandBufferImmediate = false;
|
||||
UF_MSG_DEBUG("Defer command buffer submit requested");
|
||||
}
|
||||
@ -1022,11 +949,11 @@ void UF_API uf::tick() {
|
||||
threadMain.metrics.totalFrameTimeMs.store(frameTime.count(), std::memory_order_relaxed);
|
||||
#endif
|
||||
|
||||
/* FPS Print */ if ( /*global*/::config.engine.fps.print ) {
|
||||
++/*global*/::times.frames;
|
||||
++/*global*/::times.total.frames;
|
||||
TIMER( /*global*/::config.engine.fps.every ) {
|
||||
UF_MSG_DEBUG("System: {:.3f} ms/frame | Time: {:.3f} | Frames: {} | FPS: {:.3f}", (time * 1000.0 / /*global*/::times.frames), time, /*global*/::times.frames, /*global*/::times.frames / time);
|
||||
/* FPS Print */ if ( ::config.engine.fps.print ) {
|
||||
++::times.frames;
|
||||
++::times.total.frames;
|
||||
TIMER( ::config.engine.fps.every ) {
|
||||
UF_MSG_DEBUG("System: {:.3f} ms/frame | Time: {:.3f} | Frames: {} | FPS: {:.3f}", (time * 1000.0 / ::times.frames), time, ::times.frames, ::times.frames / time);
|
||||
#if UF_ENV_DREAMCAST
|
||||
DC_STATS();
|
||||
#endif
|
||||
@ -1035,25 +962,25 @@ void UF_API uf::tick() {
|
||||
for ( auto& [ name, stats ] : metrics ) UF_MSG_DEBUG("Thread {}: active={}, idle={}, total={}, tasks={}", name, std::get<0>(stats), std::get<1>(stats), std::get<2>(stats), std::get<3>(stats) );
|
||||
#endif
|
||||
|
||||
/*global*/::times.frames = 0;
|
||||
::times.frames = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void UF_API uf::render() {
|
||||
if ( uf::scene::scenes.empty() ) return;
|
||||
|
||||
if ( /*global*/::sceneTransition.phase >= 0 ) {
|
||||
if ( ::sceneTransition.phase >= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if UF_USE_ULTRALIGHT
|
||||
/* Ultralight-UX */ if ( /*global*/::config.engine.ext.ultralight.enabled ) {
|
||||
/* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
|
||||
ext::ultralight::render();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::context ) {
|
||||
vr::VRCompositor()->SubmitExplicitTimingData();
|
||||
{
|
||||
ext::openvr::synchronize();
|
||||
}
|
||||
#endif
|
||||
/* Render scene */ {
|
||||
@ -1061,8 +988,7 @@ void UF_API uf::render() {
|
||||
uf::renderer::render();
|
||||
}
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::context ) {
|
||||
ext::openvr::synchronize();
|
||||
if ( !uf::renderer::hasRenderMode("VR") ) {
|
||||
ext::openvr::submit();
|
||||
}
|
||||
#endif
|
||||
@ -1075,22 +1001,22 @@ void UF_API uf::terminate() {
|
||||
spec::controller::terminate();
|
||||
}
|
||||
#if UF_USE_VALL_E
|
||||
if ( /*global*/::config.engine.ext.vall_e.enabled ) {
|
||||
if ( ::config.engine.ext.vall_e.enabled ) {
|
||||
ext::vall_e::terminate();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_IMGUI
|
||||
if ( /*global*/::config.engine.ext.imgui.enabled ) {
|
||||
if ( ::config.engine.ext.imgui.enabled ) {
|
||||
ext::imgui::terminate();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_ULTRALIGHT
|
||||
/* Ultralight-UX */ if ( /*global*/::config.engine.ext.ultralight.enabled ) {
|
||||
/* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
|
||||
ext::ultralight::terminate();
|
||||
}
|
||||
#endif
|
||||
#if UF_USE_OPENVR
|
||||
/* OpenVR */ if ( ext::openvr::context ) {
|
||||
/* OpenVR */ if ( ext::openvr::enabled ) {
|
||||
ext::openvr::terminate();
|
||||
}
|
||||
#endif
|
||||
@ -1113,10 +1039,10 @@ void UF_API uf::terminate() {
|
||||
{
|
||||
uf::scene::destroy();
|
||||
}
|
||||
/* Garbage collection */ if ( /*global*/::config.engine.gc.enabled ) {
|
||||
size_t collected = uf::instantiator::collect( /*global*/::config.engine.gc.mode );
|
||||
/* Garbage collection */ if ( ::config.engine.gc.enabled ) {
|
||||
size_t collected = uf::instantiator::collect( ::config.engine.gc.mode );
|
||||
if ( collected > 0 ) {
|
||||
if ( /*global*/::config.engine.gc.announce ) UF_MSG_DEBUG("GC collected {} unused entities", (int) collected);
|
||||
if ( ::config.engine.gc.announce ) UF_MSG_DEBUG("GC collected {} unused entities", (int) collected);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,14 +1070,14 @@ void UF_API uf::terminate() {
|
||||
}
|
||||
|
||||
/* Print system stats */ {
|
||||
/*global*/::times.total.time = /*global*/::times.sys.elapsed().asDouble();
|
||||
UF_MSG_DEBUG("System: Total Time: {} | Total Frames: {} | Average FPS: {}", /*global*/::times.total.time, /*global*/::times.total.frames, /*global*/::times.total.frames / /*global*/::times.total.time);
|
||||
::times.total.time = ::times.sys.elapsed().asDouble();
|
||||
UF_MSG_DEBUG("System: Total Time: {} | Total Frames: {} | Average FPS: {}", ::times.total.time, ::times.total.frames, ::times.total.frames / ::times.total.time);
|
||||
}
|
||||
|
||||
/* Flush input buffer */ {
|
||||
/*global*/::io.output << /*global*/::io.input << "\n";
|
||||
for ( const auto& str : uf::iostream.getHistory() ) /*global*/::io.output << str << "\n";
|
||||
/*global*/::io.output << "\nTerminated after " << /*global*/::times.sys.elapsed().asDouble() << " seconds" << "\n";
|
||||
/*global*/::io.output.close();
|
||||
::io.output << ::io.input << "\n";
|
||||
for ( const auto& str : uf::iostream.getHistory() ) ::io.output << str << "\n";
|
||||
::io.output << "\nTerminated after " << ::times.sys.elapsed().asDouble() << " seconds" << "\n";
|
||||
::io.output.close();
|
||||
}
|
||||
}
|
||||
@ -52,6 +52,7 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
|
||||
renderMode.blitter.descriptor.subpass = 0;
|
||||
renderMode.metadata.type = "single";
|
||||
renderMode.metadata.name = name;
|
||||
renderMode.metadata.json["vr"] = true;
|
||||
if ( uf::renderer::settings::experimental::registerRenderMode ) uf::renderer::addRenderMode( &renderMode, name );
|
||||
|
||||
metadata.boundGui = true;
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/ext/ffx/fsr.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
#include "../light/behavior.h"
|
||||
#include "../voxelizer/behavior.h"
|
||||
@ -158,11 +159,9 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
#endif
|
||||
renderMode.scale = 1.0f; // ::json["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(1.0f);
|
||||
UF_MSG_DEBUG("Geometry render scale: {:.3f}", renderMode.scale);
|
||||
/*
|
||||
if ( ::json["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
|
||||
if ( ext::openvr::enabled ) {
|
||||
renderMode.metadata.eyes = 2;
|
||||
}
|
||||
*/
|
||||
#if UF_USE_VULKAN
|
||||
if ( uf::renderer::settings::pipelines::deferred ) {
|
||||
renderMode.metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::deferred);
|
||||
|
||||
@ -1707,10 +1707,8 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) {
|
||||
auto& metadata = entity.getComponent<uf::ObjectBehavior::Metadata>();
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
|
||||
if ( !metadata.system.ignoreGraph ) {
|
||||
object.previous = object.model;
|
||||
object.model = uf::transform::model( transform );
|
||||
}
|
||||
object.previous = object.model;
|
||||
object.model = uf::transform::model( transform );
|
||||
}
|
||||
|
||||
objects.emplace_back( object );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <uf/engine/ext.h>
|
||||
#include <uf/ext/ffx/fsr.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
#define BARYCENTRIC 1
|
||||
#if BARYCENTRIC
|
||||
@ -117,7 +118,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
|
||||
struct {
|
||||
size_t id, bary, depth, depth_resolved, uv, normal;
|
||||
size_t color, scratch, motion, output;
|
||||
size_t color, scratch, motion, output, outputRightEye;
|
||||
} attachments = {};
|
||||
|
||||
bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling;
|
||||
@ -169,14 +170,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
/*.blend =*/ true,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
/*.blend =*/ false,
|
||||
/*.samples =*/ 1,
|
||||
/*.mips =*/ mips,
|
||||
@ -223,6 +224,11 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
|
||||
metadata.attachments["output"] = attachments.color;
|
||||
|
||||
if ( metadata.eyes == 2 ) {
|
||||
metadata.attachments["left"] = metadata.attachments["output"];
|
||||
metadata.attachments["right"] = metadata.attachments["scratch"];
|
||||
}
|
||||
|
||||
// First pass: fill the G-Buffer
|
||||
renderTarget.addPass(
|
||||
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
@ -449,6 +455,16 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
::postprocesses::depthPyramid.atomicCounter.initialize( (const void*) nullptr, sizeof(::AtomicCounter) * 1, uf::renderer::enums::Buffer::STORAGE | VK_BUFFER_USAGE_TRANSFER_DST_BIT );
|
||||
shader.aliasBuffer("atomicCounterDepth", ::postprocesses::depthPyramid.atomicCounter);
|
||||
}
|
||||
|
||||
if ( ext::openvr::enabled ) {
|
||||
uf::stl::string vertexShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/vr/stereo.vert.spv");
|
||||
uf::stl::string fragmentShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/vr/stereo.frag.spv");
|
||||
blitter.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "vr");
|
||||
blitter.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "vr");
|
||||
|
||||
auto& shader = blitter.material.getShader("fragment", "vr");
|
||||
shader.aliasAttachment("output", this);
|
||||
}
|
||||
}
|
||||
|
||||
this->build(true);
|
||||
@ -597,6 +613,12 @@ void ext::vulkan::DeferredRenderMode::build( bool resized ) {
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
blitter.update( descriptor );
|
||||
}
|
||||
|
||||
if ( ext::openvr::enabled ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
descriptor.pipeline = "vr";
|
||||
blitter.update( descriptor );
|
||||
}
|
||||
}
|
||||
}
|
||||
void ext::vulkan::DeferredRenderMode::tick() {
|
||||
@ -1191,6 +1213,63 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
#if UF_USE_OPENVR
|
||||
// OpenVR does not respect layered images
|
||||
if ( metadata.eyes == 2 && !ext::vulkan::hasRenderMode("VR") ) {
|
||||
auto& outputAttachment = this->getAttachment("left");
|
||||
auto& scratchAttachment = this->getAttachment("right");
|
||||
|
||||
VkImageSubresourceRange outRange = {};
|
||||
outRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
outRange.baseMipLevel = 0;
|
||||
outRange.levelCount = 1;
|
||||
outRange.baseArrayLayer = 0;
|
||||
outRange.layerCount = metadata.eyes;
|
||||
|
||||
VkImageSubresourceRange scratchRange = outRange;
|
||||
scratchRange.layerCount = 1;
|
||||
|
||||
uf::renderer::Texture::setImageLayout(
|
||||
commandBuffer, outputAttachment.image,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // Or SHADER_READ_ONLY
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
outRange
|
||||
);
|
||||
uf::renderer::Texture::setImageLayout(
|
||||
commandBuffer, scratchAttachment.image,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
scratchRange
|
||||
);
|
||||
|
||||
VkImageCopy copy = {};
|
||||
copy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copy.srcSubresource.baseArrayLayer = 1;
|
||||
copy.srcSubresource.layerCount = 1;
|
||||
copy.srcSubresource.mipLevel = 0;
|
||||
|
||||
copy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copy.dstSubresource.baseArrayLayer = 0;
|
||||
copy.dstSubresource.layerCount = 1;
|
||||
copy.dstSubresource.mipLevel = 0;
|
||||
|
||||
copy.extent = { width, height, 1 };
|
||||
|
||||
vkCmdCopyImage(
|
||||
commandBuffer,
|
||||
outputAttachment.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
scratchAttachment.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ©
|
||||
);
|
||||
|
||||
uf::renderer::Texture::setImageLayout(
|
||||
commandBuffer, scratchAttachment.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
scratchRange
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
|
||||
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/engine/ext.h>
|
||||
#include <uf/utils/io/fmt.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
const uf::stl::string ext::vulkan::RenderTargetRenderMode::getType() const {
|
||||
return "RenderTarget";
|
||||
@ -212,6 +213,19 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ext::openvr::enabled && metadata.json["vr"].as<bool>() ) {
|
||||
uf::stl::string vertexShaderFilename = uf::io::resolveURI(::fmt::format("{}/shaders/display/vr/{}.vert.spv", uf::io::root, metadata.json["stereo"].as<bool>(metadata.views == 2) ? "stereo" : "flat"));
|
||||
uf::stl::string fragmentShaderFilename = uf::io::resolveURI(::fmt::format("{}/shaders/display/vr/{}.frag.spv", uf::io::root, metadata.json["stereo"].as<bool>(metadata.views == 2) ? "stereo" : "flat"));
|
||||
|
||||
blitter.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "vr");
|
||||
blitter.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "vr");
|
||||
|
||||
{
|
||||
auto& shader = blitter.material.getShader("fragment", "vr");
|
||||
shader.aliasAttachment("color", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->build(true);
|
||||
@ -266,6 +280,12 @@ void ext::vulkan::RenderTargetRenderMode::build( bool resized ) {
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
blitter.update( descriptor );
|
||||
}
|
||||
|
||||
if ( ext::openvr::enabled && metadata.json["vr"].as<bool>() ) {
|
||||
auto descriptor = blitter.descriptor;
|
||||
descriptor.pipeline = "vr";
|
||||
blitter.update( descriptor );
|
||||
}
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderTargetRenderMode::tick() {
|
||||
|
||||
250
engine/src/ext/vulkan/rendermodes/vr.cpp
Normal file
250
engine/src/ext/vulkan/rendermodes/vr.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
#if UF_USE_VULKAN
|
||||
|
||||
#include <uf/ext/vulkan/vulkan.h>
|
||||
#include <uf/ext/vulkan/rendermodes/vr.h>
|
||||
#include <uf/ext/vulkan/initializers.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/ext/vulkan/graphic.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/engine/ext.h>
|
||||
#include <uf/utils/io/fmt.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
namespace {
|
||||
uf::Camera camera;
|
||||
}
|
||||
|
||||
const uf::stl::string ext::vulkan::VrRenderMode::getType() const {
|
||||
return "VR";
|
||||
}
|
||||
|
||||
void ext::vulkan::VrRenderMode::initialize(Device& device) {
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
metadata.pipeline = "vr";
|
||||
|
||||
ext::vulkan::RenderMode::initialize( device );
|
||||
renderTarget.device = &device;
|
||||
|
||||
struct {
|
||||
size_t left, right, depth;
|
||||
} attachments = {};
|
||||
|
||||
attachments.left = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
/*.blend =*/ true,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.right = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
/*.blend =*/ true,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */ext::vulkan::settings::formats::depth,
|
||||
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
|
||||
/*.blend = */false,
|
||||
/*.samples = */1,
|
||||
});
|
||||
|
||||
metadata.attachments["left"] = attachments.left;
|
||||
metadata.attachments["right"] = attachments.right;
|
||||
metadata.attachments["output"] = attachments.left;
|
||||
|
||||
renderTarget.addPass(
|
||||
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
/*.colors =*/ { attachments.left, attachments.right },
|
||||
/*.inputs =*/ {},
|
||||
/*.resolve =*/{},
|
||||
/*.depth = */ attachments.depth,
|
||||
/*.layer = */0,
|
||||
/*.autoBuildPipeline =*/ true
|
||||
);
|
||||
|
||||
renderTarget.initialize( device );
|
||||
|
||||
blitter.process = false;
|
||||
}
|
||||
|
||||
void ext::vulkan::VrRenderMode::createCommandBuffers(const uf::stl::vector<ext::vulkan::Graphic*>& graphics) {
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
|
||||
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
||||
|
||||
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>{"Deferred", "Compute:RT", "RenderTarget"}, false);
|
||||
|
||||
float depthClear = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
|
||||
uf::stl::vector<VkClearValue> clearValues;
|
||||
for ( auto& attachment : renderTarget.attachments ) {
|
||||
pod::Vector4f clearColor = {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 ) {
|
||||
clearValue.depthStencil = { depthClear, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
auto& commands = getCommands();
|
||||
for (size_t frame = 0; frame < commands.size(); ++frame) {
|
||||
auto& commandBuffer = commands[frame];
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &cmdBufInfo));
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::BEGIN, "begin" );
|
||||
{
|
||||
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassBeginInfo.pNext = nullptr;
|
||||
renderPassBeginInfo.renderArea.offset.x = 0;
|
||||
renderPassBeginInfo.renderArea.offset.y = 0;
|
||||
renderPassBeginInfo.renderArea.extent.width = width;
|
||||
renderPassBeginInfo.renderArea.extent.height = height;
|
||||
renderPassBeginInfo.clearValueCount = clearValues.size();
|
||||
renderPassBeginInfo.pClearValues = &clearValues[0];
|
||||
renderPassBeginInfo.renderPass = renderTarget.renderPass;
|
||||
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[frame];
|
||||
|
||||
// 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;
|
||||
|
||||
size_t subpasses = renderTarget.passes.size();
|
||||
size_t currentPass = 0;
|
||||
|
||||
// pre-renderpass commands
|
||||
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_BEGIN, commandBuffer, frame, {
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[begin]" );
|
||||
} );
|
||||
|
||||
{
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::BEGIN, "renderPass[begin]" );
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
for ( auto currentPass = 0; currentPass < 2; ++currentPass ) {
|
||||
size_t currentDraw = 0;
|
||||
for ( auto _ : layers ) {
|
||||
RenderTargetRenderMode* layer = (RenderTargetRenderMode*) _;
|
||||
auto& blitter = layer->blitter;
|
||||
if ( !blitter.initialized || !blitter.process ) continue;
|
||||
UF_MSG_DEBUG("currentPass={}, frame={}, renderMode name={}, type={}", currentPass, frame, layer->getName(), layer->getType());
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor);
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, ::fmt::format("blitter[{}: {}]", layer->getName(), layer->getType()) );
|
||||
blitter.record(commandBuffer, descriptor, currentPass, currentDraw++, frame);
|
||||
}
|
||||
}
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "renderPass[end]" );
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
}
|
||||
|
||||
|
||||
// post-renderpass commands
|
||||
VK_COMMAND_BUFFER_CALLBACK( CALLBACK_END, commandBuffer, frame, {
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "callback[end]" );
|
||||
} );
|
||||
}
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "end" );
|
||||
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
void ext::vulkan::VrRenderMode::build( bool resized ) {
|
||||
ext::vulkan::RenderMode::build();
|
||||
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
// (re)initialize pipelines
|
||||
if ( blitter.process ) {
|
||||
blitter.descriptor.bind.width = width;
|
||||
blitter.descriptor.bind.height = height;
|
||||
|
||||
blitter.update( blitter.descriptor );
|
||||
}
|
||||
}
|
||||
void ext::vulkan::VrRenderMode::tick() {
|
||||
ext::vulkan::RenderMode::tick();
|
||||
|
||||
bool resized = this->width == 0 && this->height == 0 && (ext::vulkan::states::resized || this->resized);
|
||||
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
|
||||
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
if ( resized ) {
|
||||
this->resized = false;
|
||||
renderTarget.initialize( *renderTarget.device );
|
||||
}
|
||||
if ( rebuild && blitter.process ) {
|
||||
this->build( resized );
|
||||
}
|
||||
|
||||
::camera.update();
|
||||
this->updateBuffer( (const void*) &::camera.data().viewport, sizeof(pod::Camera::Viewports), metadata.buffers["camera"] );
|
||||
}
|
||||
|
||||
void ext::vulkan::VrRenderMode::destroy() {
|
||||
ext::vulkan::RenderMode::destroy();
|
||||
}
|
||||
|
||||
void ext::vulkan::VrRenderMode::render() {
|
||||
if ( this->commands.container().empty() ) return;
|
||||
|
||||
auto& commands = getCommands( this->mostRecentCommandPoolId );
|
||||
|
||||
VK_COMMAND_BUFFER_CALLBACK( EXECUTE_BEGIN, VkCommandBuffer{}, 0, {} );
|
||||
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.pWaitDstStageMask = NULL;
|
||||
submitInfo.pWaitSemaphores = NULL;
|
||||
submitInfo.waitSemaphoreCount = 0;
|
||||
submitInfo.pSignalSemaphores = NULL;
|
||||
submitInfo.signalSemaphoreCount = 0;
|
||||
submitInfo.pCommandBuffers = &commands[states::currentBuffer];
|
||||
submitInfo.commandBufferCount = 1;
|
||||
|
||||
VkQueue queue = device->getQueue( QueueEnum::GRAPHICS );
|
||||
VkResult res = vkQueueSubmit( queue, 1, &submitInfo, /*VK_NULL_HANDLE*/fences[states::currentBuffer]);
|
||||
VK_CHECK_QUEUE_CHECKPOINT( queue, res );
|
||||
VK_COMMAND_BUFFER_CALLBACK( EXECUTE_END, VkCommandBuffer{}, 0, {} );
|
||||
|
||||
ext::openvr::submit();
|
||||
|
||||
this->executed = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -27,6 +27,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
size_t index = attachments.size();
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
uint8_t layers = descriptor.layers > 0 ? descriptor.layers : this->views;
|
||||
|
||||
if ( attachment ) {
|
||||
for ( auto& view : attachment->views ) {
|
||||
@ -66,12 +67,13 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
|
||||
attachment->descriptor.width = width;
|
||||
attachment->descriptor.height = height;
|
||||
attachment->descriptor.layers = layers;
|
||||
if ( attachment->descriptor.mips <= 1 ) {
|
||||
attachment->descriptor.mips = 1;
|
||||
} else {
|
||||
attachment->descriptor.mips = uf::vector::mips( pod::Vector2ui{ width, height } );
|
||||
}
|
||||
attachment->views.resize(this->views * attachment->descriptor.mips);
|
||||
attachment->views.resize(layers * attachment->descriptor.mips);
|
||||
|
||||
bool isSwapchain = attachment->descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
bool isDepth = attachment->descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
@ -86,7 +88,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.baseArrayLayer = 0;
|
||||
subresourceRange.aspectMask = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subresourceRange.layerCount = this->views;
|
||||
subresourceRange.layerCount = layers;
|
||||
|
||||
auto commandBuffer = device->fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS);
|
||||
for ( size_t i = 0; i < ext::vulkan::swapchain.buffers; ++i ) {
|
||||
@ -123,13 +125,13 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
imageCreateInfo.format = attachment->descriptor.format;
|
||||
imageCreateInfo.extent = { width, height, 1 };
|
||||
imageCreateInfo.mipLevels = attachment->descriptor.mips;
|
||||
imageCreateInfo.arrayLayers = this->views;
|
||||
imageCreateInfo.arrayLayers = layers;
|
||||
imageCreateInfo.samples = ext::vulkan::sampleCount( attachment->descriptor.samples );
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = attachment->descriptor.usage;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if ( this->views == 6 ) {
|
||||
if ( layers == 6 ) {
|
||||
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
}
|
||||
|
||||
@ -152,8 +154,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
VkImageViewCreateInfo imageView = {};
|
||||
imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
if ( this->views > 1 ) {
|
||||
imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
if ( layers > 1 ) {
|
||||
imageView.viewType = layers == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
}
|
||||
imageView.format = attachment->descriptor.format;
|
||||
imageView.subresourceRange = {};
|
||||
@ -161,7 +163,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
imageView.subresourceRange.baseMipLevel = 0;
|
||||
imageView.subresourceRange.baseArrayLayer = 0;
|
||||
imageView.subresourceRange.levelCount = attachment->descriptor.mips;
|
||||
imageView.subresourceRange.layerCount = this->views;
|
||||
imageView.subresourceRange.layerCount = layers;
|
||||
imageView.image = attachment->image;
|
||||
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
|
||||
VK_REGISTER_HANDLE( attachment->view );
|
||||
@ -173,7 +175,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
}
|
||||
|
||||
size_t viewIndex = 0;
|
||||
for ( size_t layer = 0; layer < this->views; ++layer ) {
|
||||
for ( size_t layer = 0; layer < layers; ++layer ) {
|
||||
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageView.subresourceRange.levelCount = 1;
|
||||
imageView.subresourceRange.layerCount = 1;
|
||||
@ -210,7 +212,7 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.baseArrayLayer = 0;
|
||||
subresourceRange.levelCount = attachment->descriptor.mips;
|
||||
subresourceRange.layerCount = this->views;
|
||||
subresourceRange.layerCount = layers;
|
||||
subresourceRange.aspectMask = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
uf::renderer::Texture::setImageLayout( commandBuffer, attachment->image, VK_IMAGE_LAYOUT_UNDEFINED, attachment->descriptor.layout, subresourceRange );
|
||||
device->flushCommandBuffer(commandBuffer, uf::renderer::QueueEnum::GRAPHICS);
|
||||
@ -493,7 +495,7 @@ void ext::vulkan::RenderTarget::destroy() {
|
||||
attachment.view = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
for ( size_t i = 0; i < this->views; ++i ) {
|
||||
for ( size_t i = 0; i < attachment.views.size(); ++i ) {
|
||||
vkDestroyImageView(*device, attachment.views[i], nullptr);
|
||||
VK_UNREGISTER_HANDLE( attachment.views[i] );
|
||||
}
|
||||
|
||||
@ -13,8 +13,8 @@ pod::Vector3f uf::camera::eye( const pod::Camera& camera, int i ) {
|
||||
if ( i < 0 ) i = 0;
|
||||
pod::Vector3f position = uf::transform::flatten( camera.transform ).position;
|
||||
#if UF_USE_OPENVR
|
||||
if ( camera.stereoscopic && ext::openvr::context ) {
|
||||
position += ext::openvr::hmdPosition( eye == 0 ? vr::Eye_Left : vr::Eye_Right );
|
||||
if ( camera.stereoscopic && ext::openvr::enabled ) {
|
||||
position += ext::openvr::hmdPosition( i == 0 ? vr::Eye_Left : vr::Eye_Right );
|
||||
}
|
||||
#endif
|
||||
return position;
|
||||
@ -39,10 +39,8 @@ void uf::camera::projection( pod::Camera& camera, const pod::Matrix4f& mat, int
|
||||
}
|
||||
void uf::camera::update( pod::Camera& camera ) {
|
||||
#if UF_USE_OPENVR
|
||||
if ( this->stereoscopic && ext::openvr::context ) {
|
||||
camera.transform.orientation = uf::quaternion::identity();
|
||||
if ( camera.stereoscopic && ext::openvr::enabled ) {
|
||||
auto view = uf::matrix::inverse( uf::transform::model( camera.transform ) );
|
||||
camera.transform.orientation = ext::openvr::hmdQuaternion();
|
||||
|
||||
uf::camera::view( camera, ext::openvr::hmdViewMatrix(vr::Eye_Left, view ), 0 );
|
||||
uf::camera::view( camera, ext::openvr::hmdViewMatrix(vr::Eye_Right, view ), 1 );
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
ifneq (,$(findstring -DUF_DEV_ENV,$(FLAGS)))
|
||||
REQ_DEPS += meshoptimizer toml xatlas curl dc:texconv # ffx:sdk vall_e cpptrace # openvr # ncurses draco discord bullet ultralight-ux
|
||||
REQ_DEPS += meshoptimizer toml xatlas curl dc:texconv ffx:sdk openvr # vall_e cpptrace # ncurses draco discord ultralight-ux
|
||||
FLAGS += -march=native -g # -flto # -g
|
||||
endif
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user