Commit for 2020.10.21.7z

This commit is contained in:
mrq 2020-10-21 00:00:00 -05:00
parent 1393f1b77a
commit 7027ce2db7
36 changed files with 352 additions and 703 deletions

View File

@ -1,4 +1,4 @@
.PHONY: win64 .PHONY: win64
TARGET_NAME = program TARGET_NAME = program
BIN_DIR = ./bin BIN_DIR = ./bin
@ -15,19 +15,19 @@ UF_LIBS =
# EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52 # EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52
# EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype # EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype
EXT_LIBS = EXT_LIBS =
#FLAGS = -Og -DUF_DISABLE_ALIGNAS -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW #FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW
FLAGS = -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW FLAGS = -Og -std=c++17 -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW
#-march=native #-march=native
LIB_NAME = uf LIB_NAME = uf
EXT_LIB_NAME = ext EXT_LIB_NAME = ext
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.101.0/ #VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.101.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.108.0/ #VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.108.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.114.0/ #VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.114.0/
#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/ #VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/
VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/ VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/
WIN64_CC = g++ WIN64_CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++
WIN64_GLSL_VALIDATOR = $(VULKAN_WIN64_SDK_PATH)/Bin32/glslangValidator WIN64_GLSL_VALIDATOR = $(VULKAN_WIN64_SDK_PATH)/Bin32/glslangValidator
# Base Engine's DLL # Base Engine's DLL
WIN64_INC_DIR = $(ENGINE_INC_DIR)/win64 WIN64_INC_DIR = $(ENGINE_INC_DIR)/win64
@ -39,8 +39,8 @@ WIN64_FLAGS = $(FLAGS) -g
#-Wl,-subsystem,windows #-Wl,-subsystem,windows
WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/ WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/
WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include
WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib
SRCS_WIN64_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_WIN64_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)
OBJS_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_WIN64_DLL)) OBJS_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_WIN64_DLL))
@ -56,8 +56,8 @@ EXT_WIN64_FLAGS = $(FLAGS)
#-Wl,-subsystem,windows #-Wl,-subsystem,windows
EXT_WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/ EXT_WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/
EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include
EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib
SRCS_EXT_WIN64_DLL = $(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) SRCS_EXT_WIN64_DLL = $(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)
OBJS_EXT_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_EXT_WIN64_DLL)) OBJS_EXT_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_EXT_WIN64_DLL))
@ -72,10 +72,6 @@ TARGET_WIN64 = $(BIN_DIR)/$(TARGET_NAME).exe
SRCS_SHADERS = $(wildcard bin/data/shaders/*.glsl) SRCS_SHADERS = $(wildcard bin/data/shaders/*.glsl)
TARGET_SHADERS = $(patsubst %.glsl,%.spv,$(SRCS_SHADERS)) TARGET_SHADERS = $(patsubst %.glsl,%.spv,$(SRCS_SHADERS))
# clang-win64: WIN64_CC=clang++
# make
# gcc-win64: WIN64_CC=g++
# make
win64: $(EX_WIN64_DLL) $(EXT_EX_WIN64_DLL) $(TARGET_WIN64) $(TARGET_SHADERS) win64: $(EX_WIN64_DLL) $(EXT_EX_WIN64_DLL) $(TARGET_WIN64) $(TARGET_SHADERS)
rm-exe64: rm-exe64:

View File

@ -32,6 +32,7 @@ struct Light {
vec3 color; vec3 color;
float power; float power;
vec2 type; vec2 type;
vec2 padding;
mat4 view; mat4 view;
mat4 projection; mat4 projection;
}; };
@ -44,6 +45,7 @@ struct State {
struct Fog { struct Fog {
vec2 range; vec2 range;
vec2 padding;
vec4 color; vec4 color;
}; };

View File

@ -1,10 +1,10 @@
template<typename C> template<typename C>
pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType( const std::string& name ) { typename pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType( const std::string& name ) {
for ( auto pair : names ) if ( pair.second == name ) return pair.first; for ( auto pair : names ) if ( pair.second == name ) return pair.first;
return getType<void>(); return getType<void>();
} }
template<typename C> template<typename C>
template<typename T> pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType() { template<typename T> typename pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType() {
return std::type_index(typeid(T)); return std::type_index(typeid(T));
} }
template<typename C> template<typename C>

View File

@ -97,6 +97,8 @@ namespace ext {
}; };
VkQueue& getQueue( QueueEnum ); VkQueue& getQueue( QueueEnum );
VkCommandPool& getCommandPool( QueueEnum ); VkCommandPool& getCommandPool( QueueEnum );
VkQueue& getQueue( QueueEnum, std::thread::id );
VkCommandPool& getCommandPool( QueueEnum, std::thread::id );
// RAII // RAII
void initialize(); void initialize();

View File

@ -104,6 +104,7 @@ namespace ext {
Pipeline& getPipeline( Descriptor& descriptor ); Pipeline& getPipeline( Descriptor& descriptor );
void record( VkCommandBuffer commandBuffer ); void record( VkCommandBuffer commandBuffer );
void record( VkCommandBuffer commandBuffer, Descriptor& descriptor );
}; };
} }
} }

View File

@ -8,6 +8,7 @@ namespace ext {
struct UF_API RenderMode { struct UF_API RenderMode {
bool execute = false; bool execute = false;
bool rebuild = false;
uint32_t width = 0, height = 0; uint32_t width = 0, height = 0;
std::string name = ""; std::string name = "";
@ -16,18 +17,25 @@ namespace ext {
VkSemaphore renderCompleteSemaphore; VkSemaphore renderCompleteSemaphore;
std::vector<VkFence> fences; std::vector<VkFence> fences;
std::vector<VkCommandBuffer> commands;
typedef std::vector<VkCommandBuffer> commands_container_t;
std::thread::id mostRecentCommandPoolId;
std::unordered_map<std::thread::id, commands_container_t> commands;
// virtual ~RenderMode(); // virtual ~RenderMode();
// RAII // RAII
virtual std::string getType() const; virtual std::string getType() const;
const std::string& getName() const; const std::string& getName( bool = false ) const;
virtual RenderTarget& getRenderTarget(size_t = 0); virtual RenderTarget& getRenderTarget(size_t = 0);
virtual const RenderTarget& getRenderTarget(size_t = 0) const; virtual const RenderTarget& getRenderTarget(size_t = 0) const;
virtual commands_container_t& getCommands();
virtual commands_container_t& getCommands( std::thread::id );
virtual void initialize( Device& device ); virtual void initialize( Device& device );
virtual void createCommandBuffers(); virtual void createCommandBuffers();
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ); virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void bindPipelines( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void tick(); virtual void tick();
virtual void render(); virtual void render();
virtual void destroy(); virtual void destroy();

View File

@ -14,6 +14,7 @@ namespace ext {
// RAII // RAII
virtual std::string getType() const; virtual std::string getType() const;
virtual const std::string& getName( bool ) const;
virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ); virtual void createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics );
virtual void initialize( Device& device ); virtual void initialize( Device& device );

View File

@ -25,8 +25,11 @@ namespace uf {
Audio( Audio&& ); Audio( Audio&& );
Audio( const Audio& ); Audio( const Audio& );
*/ */
~Audio();
bool initialized(); bool initialized();
bool playing(); bool playing();
void destroy();
void load( const std::string& = "" ); void load( const std::string& = "" );
void play(); void play();

View File

@ -10,13 +10,11 @@ namespace {
// Sometimes uint isn't declared // Sometimes uint isn't declared
typedef unsigned int uint; typedef unsigned int uint;
} }
/*
namespace uf { namespace uf {
namespace math { namespace math {
template<typename T> template<typename T>
T lerp( const T& from, const T& to, double delta ) { T lerp( const T& a, const T& b, double f ) {
return a + f * (b - a);
} }
} }
} }
*/

View File

@ -6,6 +6,7 @@
namespace uf { namespace uf {
namespace io { namespace io {
std::string UF_API absolute( const std::string& );
std::string UF_API filename( const std::string& ); std::string UF_API filename( const std::string& );
std::string UF_API extension( const std::string& ); std::string UF_API extension( const std::string& );
std::string UF_API directory( const std::string& ); std::string UF_API directory( const std::string& );

View File

@ -9,6 +9,7 @@
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <condition_variable>
namespace pod { namespace pod {
struct UF_API Thread { struct UF_API Thread {
@ -22,6 +23,7 @@ namespace pod {
bool running, terminates; bool running, terminates;
std::mutex* mutex; std::mutex* mutex;
std::condition_variable condition;
std::thread thread; std::thread thread;
pod::Thread::queue_t temps; pod::Thread::queue_t temps;
@ -45,6 +47,7 @@ namespace uf {
// void UF_API tick( pod::Thread&, const std::function<void()>& = NULL ); // void UF_API tick( pod::Thread&, const std::function<void()>& = NULL );
pod::Thread& UF_API fetchWorker( const std::string& name = "Aux" ); pod::Thread& UF_API fetchWorker( const std::string& name = "Aux" );
void UF_API batchWorkers( const std::vector<pod::Thread::function_t>&, bool = true, const std::string& name = "Aux" );
void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false ); void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false );
void UF_API process( pod::Thread& ); void UF_API process( pod::Thread& );

View File

@ -31,6 +31,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
// //
{ {
size_t assets = metadata["system"]["assets"].size(); size_t assets = metadata["system"]["assets"].size();
if ( metadata["system"]["load"]["ignore"].isBool() ) assets = 0;
metadata["system"]["load"]["progress"] = 0; metadata["system"]["load"]["progress"] = 0;
metadata["system"]["load"]["total"] = assets; metadata["system"]["load"]["total"] = assets;
if ( assets == 0 ) { if ( assets == 0 ) {
@ -62,6 +63,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{ this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event; uf::Serializer json = event;
std::string filename = json["filename"].asString(); std::string filename = json["filename"].asString();
bool initialize = json["initialize"].isNull() ? true : json["initialize"].asBool();
if ( uf::io::extension(filename) != "json" ) return "false"; if ( uf::io::extension(filename) != "json" ) return "false";
@ -72,7 +74,8 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
json["root"] = uf::io::directory(filename); json["root"] = uf::io::directory(filename);
json["source"] = filename; // uf::io::filename(filename) json["source"] = filename; // uf::io::filename(filename)
json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10; json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10;
if ( this->loadChildUid(json) == -1 ) return "false";
if ( this->loadChildUid(json, initialize) == -1 ) return "false";
return "true"; return "true";
}); });

View File

@ -87,6 +87,7 @@ void uf::LoadingBehavior::tick( uf::Object& self ) {
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) { std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getUid() == 0 || !entity->hasComponent<uf::Serializer>() ) return; if ( !entity || entity->getUid() == 0 || !entity->hasComponent<uf::Serializer>() ) return;
auto& metadata = entity->getComponent<uf::Serializer>(); auto& metadata = entity->getComponent<uf::Serializer>();
if ( metadata["system"]["load"]["ignore"].isBool() ) return;
if ( metadata["system"]["load"].isNull() ) return; if ( metadata["system"]["load"].isNull() ) return;
++loading; ++loading;
if ( metadata["system"]["load"]["progress"].asInt() < metadata["system"]["load"]["total"].asInt() ) return; if ( metadata["system"]["load"]["progress"].asInt() < metadata["system"]["load"]["total"].asInt() ) return;

View File

@ -31,9 +31,11 @@ bool UF_API_CALL ext::AL::initialize() {
} }
return this->m_initialized = true; return this->m_initialized = true;
*/ */
bool res = this->m_initialized = (alutInit(NULL, NULL) == AL_TRUE); this->m_initialized = alutInit(NULL, NULL) == AL_TRUE;
auto error = alutGetError();
std::cout << alutGetErrorString(error) << std::endl;
this->checkError(__FUNCTION__, __LINE__); this->checkError(__FUNCTION__, __LINE__);
return res; return this->m_initialized;
} }
bool UF_API_CALL ext::AL::terminate() { bool UF_API_CALL ext::AL::terminate() {
/* /*
@ -46,7 +48,9 @@ bool UF_API_CALL ext::AL::terminate() {
} }
void UF_API_CALL ext::AL::checkError( const std::string& function, int line, const std::string& aux ) const { void UF_API_CALL ext::AL::checkError( const std::string& function, int line, const std::string& aux ) const {
std::string error = this->getError(); std::string error = this->getError();
// if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl; if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl;
error = alutGetErrorString(alutGetError());
if ( error != "No ALUT error found" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl;
} }
std::string UF_API_CALL ext::AL::getError() const { std::string UF_API_CALL ext::AL::getError() const {
ALCenum error = alGetError(); ALCenum error = alGetError();
@ -58,7 +62,7 @@ std::string UF_API_CALL ext::AL::getError() const {
case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION"; // the requested operation is not valid case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION"; // the requested operation is not valid
case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY"; // the requested operation resulted in OpenAL running out ofmemory case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY"; // the requested operation resulted in OpenAL running out ofmemory
} }
return "AL_UNKNOWN"; return "AL_UNKNOWN(" + std::to_string(error) + ")";
} }
void UF_API_CALL ext::AL::listener( ALenum name, std::vector<ALfloat> parameters ) { void UF_API_CALL ext::AL::listener( ALenum name, std::vector<ALfloat> parameters ) {
switch ( parameters.size() ) { switch ( parameters.size() ) {
@ -86,13 +90,12 @@ ext::al::Source::~Source() {
void UF_API_CALL ext::al::Source::generate() { void UF_API_CALL ext::al::Source::generate() {
if ( this->m_index ) this->destroy(); if ( this->m_index ) this->destroy();
alGenSources(1, &this->m_index); alGenSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__);
ext::oal.checkError(__FUNCTION__, __LINE__);
} }
void UF_API_CALL ext::al::Source::destroy() { void UF_API_CALL ext::al::Source::destroy() {
if ( this->m_index && alIsSource(this->m_index) ) { if ( this->m_index && alIsSource(this->m_index) ) {
alDeleteSources(1, &this->m_index); if ( this->playing() ) this->stop();
ext::oal.checkError(__FUNCTION__, __LINE__); alDeleteSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__);
} }
this->m_index = 0; this->m_index = 0;
} }

View File

@ -1,12 +1,11 @@
#include <uf/ext/openvr/openvr.h> #include <uf/ext/openvr/openvr.h>
#include <uf/utils/io/iostream.h> #include <uf/utils/io/iostream.h>
#include <uf/utils/string/ext.h> #include <uf/utils/string/ext.h>
#include <uf/utils/string/io.h>
#include <uf/ext/vulkan/vulkan.h> #include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h> #include <uf/ext/vulkan/rendermodes/stereoscopic_deferred.h>
#include <stdlib.h>
#include <filesystem>
#define DEBUG_MARKER 0 #define DEBUG_MARKER 0
vr::IVRSystem* ext::openvr::context; vr::IVRSystem* ext::openvr::context;
@ -156,10 +155,7 @@ bool ext::openvr::initialize( int stage ) {
// load manifest // load manifest
{ {
std::filesystem::path p = ext::openvr::driver.manifest; VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( uf::io::absolute(ext::openvr::driver.manifest).c_str() ) );
p = std::filesystem::absolute( p );
ext::openvr::driver.manifest = p.string();
VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( ext::openvr::driver.manifest.c_str() ) );
// configure action handles // configure action handles
{ {
uf::Serializer manifest; uf::Serializer manifest;

View File

@ -435,11 +435,16 @@ VkResult ext::vulkan::Device::createBuffer(
// Attach the memory to the buffer object // Attach the memory to the buffer object
return buffer.bind(); return buffer.bind();
} }
VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum ) { VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum) {
return this->getCommandPool( queueEnum, std::this_thread::get_id() );
}
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) {
return this->getQueue( queueEnum, std::this_thread::get_id() );
}
VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) {
uint32_t index = 0; uint32_t index = 0;
VkCommandPool* pool = NULL; VkCommandPool* pool = NULL;
bool exists = false; bool exists = false;
auto id = std::this_thread::get_id();
switch ( queueEnum ) { switch ( queueEnum ) {
case QueueEnum::GRAPHICS: case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics; index = device.queueFamilyIndices.graphics;
@ -468,11 +473,10 @@ VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEn
} }
return *pool; return *pool;
} }
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) { VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) {
uint32_t index = 0; uint32_t index = 0;
VkQueue* queue = NULL; VkQueue* queue = NULL;
bool exists = false; bool exists = false;
auto id = std::this_thread::get_id();
switch ( queueEnum ) { switch ( queueEnum ) {
case QueueEnum::GRAPHICS: case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics; index = device.queueFamilyIndices.graphics;

View File

@ -479,6 +479,9 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
// generate fallback empty texture // generate fallback empty texture
auto& emptyTexture = Texture2D::empty; auto& emptyTexture = Texture2D::empty;
RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true);
auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget );
std::vector<VkWriteDescriptorSet> writeDescriptorSets; std::vector<VkWriteDescriptorSet> writeDescriptorSets;
std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings; std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
std::vector<VkDescriptorImageInfo> inputDescriptors; std::vector<VkDescriptorImageInfo> inputDescriptors;
@ -488,9 +491,6 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() ); descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() );
} }
RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true);
auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget );
if ( graphic.descriptor.subpass < renderTarget.passes.size() ) { if ( graphic.descriptor.subpass < renderTarget.passes.size() ) {
auto& subpass = renderTarget.passes[graphic.descriptor.subpass]; auto& subpass = renderTarget.passes[graphic.descriptor.subpass];
for ( auto& input : subpass.inputs ) { for ( auto& input : subpass.inputs ) {
@ -563,6 +563,8 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
if ( d.imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) if ( d.imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL )
d.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; d.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
} else {
// std::cout << "textures == graphic.material.textures.end()" << std::endl;
} }
imageInfos.push_back( d ); imageInfos.push_back( d );
} }
@ -668,10 +670,11 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
for ( auto& descriptor : writeDescriptorSets ) { for ( auto& descriptor : writeDescriptorSets ) {
if ( descriptor.pBufferInfo ) { if ( descriptor.pBufferInfo ) {
// std::cout << descriptor.pBufferInfo->offset << std::endl; // std::cout << descriptor.pBufferInfo->offset << std::endl;
if ( descriptor.pBufferInfo->offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl; if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo->buffer << " " << descriptor.pBufferInfo->offset << " " << descriptor.pBufferInfo->range << ", invalidating..." << std::endl; // std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo[i].offset << std::endl;
auto pointer = const_cast<VkDescriptorBufferInfo*>(descriptor.pBufferInfo); std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " " << descriptor.pBufferInfo[i].offset << " " << descriptor.pBufferInfo[i].range << ", invalidating..." << std::endl;
auto pointer = const_cast<VkDescriptorBufferInfo*>(&descriptor.pBufferInfo[i]);
pointer->offset = 0; pointer->offset = 0;
pointer->range = 0; pointer->range = 0;
pointer->buffer = VK_NULL_HANDLE; pointer->buffer = VK_NULL_HANDLE;
@ -680,7 +683,22 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
} }
} }
} }
}
// render mode's command buffer is in flight, queue a rebuild
// ext::vulkan::rebuild = true;
// renderMode.synchronize();
renderMode.rebuild = true;
/*
std::cout << this << ": " << renderMode.getName() << ": " << renderMode.getType() << " " << descriptorSet << std::endl;
for ( auto& descriptor : writeDescriptorSets ) {
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
if ( descriptor.pImageInfo ) {
std::cout << "[" << i << "]: " << descriptor.pImageInfo[i].imageView << std::endl;
}
}
}
*/
vkUpdateDescriptorSets( vkUpdateDescriptorSets(
*device, *device,
writeDescriptorSets.size(), writeDescriptorSets.size(),
@ -780,12 +798,15 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline( Descriptor& descriptor
return pipelines[descriptor.hash()]; return pipelines[descriptor.hash()];
} }
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer ) { void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer ) {
return this->record( commandBuffer, descriptor );
}
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, Descriptor& descriptor ) {
if ( !this->hasPipeline( descriptor ) ) { if ( !this->hasPipeline( descriptor ) ) {
std::cout << this << ": has no valid pipeline" << std::endl; std::cout << this << ": has no valid pipeline" << std::endl;
return; return;
} }
auto& pipeline = this->getPipeline(); auto& pipeline = this->getPipeline( descriptor );
assert( buffers.size() >= 2 ); assert( buffers.size() >= 2 );
Buffer& vertexBuffer = buffers.at(0); Buffer& vertexBuffer = buffers.at(0);

View File

@ -17,7 +17,7 @@ ext::vulkan::RenderMode::~RenderMode() {
std::string ext::vulkan::RenderMode::getType() const { std::string ext::vulkan::RenderMode::getType() const {
return ""; return "";
} }
const std::string& ext::vulkan::RenderMode::getName() const { const std::string& ext::vulkan::RenderMode::getName( bool ) const {
return this->name; return this->name;
} }
ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) { ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) {
@ -52,13 +52,78 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
} }
this->synchronize(); this->synchronize();
//VK_CHECK_RESULT(vkWaitForFences(*device, fences.size(), fences.data(), VK_TRUE, UINT64_MAX)); bindPipelines( graphics );
createCommandBuffers( graphics ); createCommandBuffers( graphics );
this->mostRecentCommandPoolId = std::this_thread::get_id();
this->rebuild = false;
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands() {
return getCommands( std::this_thread::get_id() );
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands( std::thread::id id ) {
bool exists = this->commands.count(id) > 0;
auto& commands = this->commands[id];
if ( !exists ) {
commands.resize( swapchain.buffers );
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS),
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
static_cast<uint32_t>(commands.size())
);
VK_CHECK_RESULT(vkAllocateCommandBuffers(*device, &cmdBufAllocateInfo, commands.data()));
}
return commands;
/*
VkCommandPool* pool = NULL;
switch ( queueEnum ) {
case QueueEnum::GRAPHICS:
index = device.queueFamilyIndices.graphics;
if ( commandPool.graphics.count(id) > 0 ) exists = true;
pool = &commandPool.graphics[id];
break;
case QueueEnum::COMPUTE:
index = device.queueFamilyIndices.compute;
if ( commandPool.compute.count(id) > 0 ) exists = true;
pool = &commandPool.compute[id];
break;
case QueueEnum::TRANSFER:
index = device.queueFamilyIndices.transfer;
if ( commandPool.transfer.count(id) > 0 ) exists = true;
pool = &commandPool.transfer[id];
break;
}
if ( !exists ) {
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VkCommandPoolCreateInfo cmdPoolInfo = {};
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmdPoolInfo.queueFamilyIndex = index;
cmdPoolInfo.flags = createFlags;
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, pool ) != VK_SUCCESS )
throw std::runtime_error("failed to create command pool for graphics!");
}
return *pool;
*/
} }
void ext::vulkan::RenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) { void ext::vulkan::RenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
}
void ext::vulkan::RenderMode::bindPipelines( const std::vector<ext::vulkan::Graphic*>& graphics ) {
for ( auto* pointer : graphics ) {
auto& graphic = *pointer;
// copy descriptor
ext::vulkan::Graphic::Descriptor descriptor = graphic.descriptor;
// bind to this render mode
descriptor.renderMode = this->getName();
// ignore if pipeline exists for this render mode
if ( graphic.hasPipeline( descriptor ) ) continue;
graphic.initializePipeline( descriptor );
}
} }
void ext::vulkan::RenderMode::render() { void ext::vulkan::RenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer) // Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer, swapchain.presentCompleteSemaphore)); VK_CHECK_RESULT(swapchain.acquireNextImage(&currentBuffer, swapchain.presentCompleteSemaphore));
@ -101,6 +166,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
} }
// Create command buffers // Create command buffers
/*
{ {
commands.resize( swapchain.buffers ); commands.resize( swapchain.buffers );
@ -112,6 +178,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data())); VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data()));
} }
*/
// Set sync objects // Set sync objects
{ {
// Fences (Used to check draw command buffer completion) // Fences (Used to check draw command buffer completion)
@ -119,7 +186,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
// Create in signaled state so we don't wait on first render of each command buffer // Create in signaled state so we don't wait on first render of each command buffer
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
fences.resize( commands.size() ); fences.resize( swapchain.buffers );
for ( auto& fence : fences ) { for ( auto& fence : fences ) {
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
} }
@ -143,12 +210,16 @@ void ext::vulkan::RenderMode::destroy() {
this->synchronize(); this->synchronize();
renderTarget.destroy(); renderTarget.destroy();
/*
if ( commands.size() > 0 ) { if ( commands.size() > 0 ) {
vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), static_cast<uint32_t>(commands.size()), commands.data()); vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), static_cast<uint32_t>(commands.size()), commands.data());
} }
commands.clear(); commands.clear();
*/
for ( auto& pair : this->commands ) {
vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast<uint32_t>(pair.second.size()), pair.second.data());
pair.second.clear();
}
if ( renderCompleteSemaphore != VK_NULL_HANDLE ) { if ( renderCompleteSemaphore != VK_NULL_HANDLE ) {
vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr); vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr);
renderCompleteSemaphore = VK_NULL_HANDLE; renderCompleteSemaphore = VK_NULL_HANDLE;

View File

@ -18,9 +18,6 @@ ext::vulkan::BaseRenderMode::~BaseRenderMode() {
std::string ext::vulkan::BaseRenderMode::getType() const { std::string ext::vulkan::BaseRenderMode::getType() const {
return "Swapchain"; return "Swapchain";
} }
const std::string& ext::vulkan::BaseRenderMode::getName() const {
return this->name;
}
void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) { void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::vulkan::Graphic*>& graphics ) {
if ( ext::vulkan::renderModes.size() > 1 ) return; if ( ext::vulkan::renderModes.size() > 1 ) return;
@ -47,6 +44,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector<ext::v
renderPassBeginInfo.renderArea.extent.height = height; renderPassBeginInfo.renderArea.extent.height = height;
renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.pClearValues = clearValues;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) { for (size_t i = 0; i < commands.size(); ++i) {
// Set target frame buffer // Set target frame buffer
renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i]; renderPassBeginInfo.framebuffer = renderTarget.framebuffers[i];

View File

@ -44,25 +44,18 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
auto& metadata = scene.getComponent<uf::Serializer>(); auto& metadata = scene.getComponent<uf::Serializer>();
auto& shader = compute.material.shaders.front(); auto& shader = compute.material.shaders.front();
/*
struct SpecializationConstant { struct SpecializationConstant {
int32_t eyes = 2;
int32_t maxLights = 16;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64();
specializationConstants.eyes = ext::openvr::context ? 2 : 1;
*/
struct SpecializationConstant {
uint32_t eyes = 2;
uint32_t maxLights = 16; uint32_t maxLights = 16;
uint32_t eyes = 2;
}; };
auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0]; auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0];
specializationConstants->maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64(); specializationConstants->maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64();
specializationConstants->eyes = ext::openvr::context ? 2 : 1; specializationConstants->eyes = ext::openvr::context ? 2 : 1;
for ( auto& binding : shader.descriptorSetLayoutBindings ) { for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 ) if ( binding.descriptorCount > 1 ) {
binding.descriptorCount = specializationConstants->maxLights; binding.descriptorCount = specializationConstants->eyes;
}
} }
} }
@ -106,6 +99,7 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
void ext::vulkan::ComputeRenderMode::render() { void ext::vulkan::ComputeRenderMode::render() {
if ( compute.buffers.empty() ) return; if ( compute.buffers.empty() ) return;
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit compute commands // Submit compute commands
// Use a fence to ensure that compute command buffer has finished executing before using it again // Use a fence to ensure that compute command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX ));
@ -143,13 +137,10 @@ void ext::vulkan::ComputeRenderMode::tick() {
texture = computeTexture; texture = computeTexture;
texture.device = NULL; texture.device = NULL;
} }
auto& pipeline = blitter.getPipeline(); blitter.getPipeline().update( blitter );
pipeline.update( blitter );
} }
// if ( compute.initialized ) {
if ( !compute.buffers.empty() ) { if ( !compute.buffers.empty() ) {
auto& pipeline = compute.getPipeline(); compute.getPipeline().update( compute );
pipeline.update( compute );
} }
} }
} }
@ -212,14 +203,16 @@ void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) {
float width = this->width > 0 ? this->width : ext::vulkan::width; float width = this->width > 0 ? this->width : ext::vulkan::width;
float height = this->height > 0 ? this->height : ext::vulkan::height; float height = this->height > 0 ? this->height : ext::vulkan::height;
if ( compute.buffers.empty() ) return;
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
auto& pipeline = compute.getPipeline(); auto& pipeline = compute.getPipeline();
auto& commands = getCommands();
if ( compute.buffers.empty() ) return;
for (size_t i = 0; i < commands.size(); ++i) { for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
pipeline.record(compute, commands[i]); pipeline.record(compute, commands[i]);
vkCmdDispatch(commands[i], width / dispatchSize.x, height / dispatchSize.y, 1); vkCmdDispatch(commands[i], width / dispatchSize.x, height / dispatchSize.y, 1);
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
} }
this->mostRecentCommandPoolId = std::this_thread::get_id();
} }

View File

@ -11,7 +11,7 @@
#include <uf/ext/vulkan/graphic.h> #include <uf/ext/vulkan/graphic.h>
std::string ext::vulkan::DeferredRenderMode::getType() const { std::string ext::vulkan::DeferredRenderMode::getType( ) const {
return "Deferred"; return "Deferred";
} }
@ -160,9 +160,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
renderTarget.initialize( *renderTarget.device ); renderTarget.initialize( *renderTarget.device );
// update blitter descriptor set // update blitter descriptor set
if ( blitter.initialized ) { if ( blitter.initialized ) {
auto& pipeline = blitter.getPipeline(); blitter.getPipeline().update( blitter );
pipeline.update( blitter );
ext::vulkan::rebuild = true;
} }
} }
} }
@ -193,6 +191,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
std::vector<RenderMode*> layers = ext::vulkan::getRenderModes(std::vector<std::string>{"RenderTarget", "Compute"}, false); std::vector<RenderMode*> layers = ext::vulkan::getRenderModes(std::vector<std::string>{"RenderTarget", "Compute"}, false);
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>(); auto& metadata = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) { for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// Fill GBuffer // Fill GBuffer

View File

@ -8,6 +8,9 @@
std::string ext::vulkan::RenderTargetRenderMode::getType() const { std::string ext::vulkan::RenderTargetRenderMode::getType() const {
return "RenderTarget"; return "RenderTarget";
} }
const std::string& ext::vulkan::RenderTargetRenderMode::getName( bool wantsTarget ) const {
return wantsTarget ? this->target : this->name;
}
void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device ); ext::vulkan::RenderMode::initialize( device );
@ -125,6 +128,7 @@ void ext::vulkan::RenderTargetRenderMode::destroy() {
blitter.destroy(); blitter.destroy();
} }
void ext::vulkan::RenderTargetRenderMode::render() { void ext::vulkan::RenderTargetRenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands // Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again // Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX ));
@ -219,7 +223,7 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
VkCommandBufferBeginInfo cmdBufInfo = {}; VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr; cmdBufInfo.pNext = nullptr;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) { for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
{ {
@ -265,7 +269,9 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
vkCmdSetScissor(commands[i], 0, 1, &scissor); vkCmdSetScissor(commands[i], 0, 1, &scissor);
for ( auto graphic : graphics ) { for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->target ) continue; if ( graphic->descriptor.renderMode != this->target ) continue;
graphic->record(commands[i] ); ext::vulkan::Graphic::Descriptor descriptor = graphic->descriptor;
descriptor.renderMode = this->name;
graphic->record(commands[i], descriptor );
} }
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
vkCmdEndRenderPass(commands[i]); vkCmdEndRenderPass(commands[i]);

View File

@ -196,7 +196,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>(); auto& metadata = scene.getComponent<uf::Serializer>();
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) { for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
struct EYES { struct EYES {

View File

@ -443,7 +443,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = format; imageCreateInfo.format = format;
imageCreateInfo.extent = { width, height, 1 }; imageCreateInfo.extent = { width, height, 1 };
imageCreateInfo.mipLevels = 1; imageCreateInfo.mipLevels = this->mips = 1;
imageCreateInfo.arrayLayers = 1; imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;

View File

@ -7,6 +7,7 @@
#include <ostream> #include <ostream>
#include <fstream> #include <fstream>
#include <atomic>
uint32_t ext::vulkan::width = 1280; uint32_t ext::vulkan::width = 1280;
uint32_t ext::vulkan::height = 720; uint32_t ext::vulkan::height = 720;
@ -302,11 +303,23 @@ void ext::vulkan::tick() {
} }
renderMode->tick(); renderMode->tick();
} }
std::vector<std::function<int()>> jobs;
for ( auto& renderMode : renderModes ) { for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue; if ( !renderMode ) continue;
if ( ext::vulkan::rebuild ) if ( ext::vulkan::rebuild || renderMode->rebuild ) {
jobs.emplace_back([&]{
renderMode->createCommandBuffers(); renderMode->createCommandBuffers();
return 0;
});
} }
}
if ( !jobs.empty() ) {
// std::cout << "Batching " << jobs.size() << " command buffer jobs" << std::endl;
uf::thread::batchWorkers( jobs );
// std::cout << "Done" << std::endl;
}
ext::vulkan::rebuild = false; ext::vulkan::rebuild = false;
ext::vulkan::resized = false; ext::vulkan::resized = false;
ext::vulkan::mutex.unlock(); ext::vulkan::mutex.unlock();

View File

@ -3,6 +3,7 @@
#if defined(UF_USE_OPENAL) #if defined(UF_USE_OPENAL)
#include <uf/ext/vorbis/vorbis.h> #include <uf/ext/vorbis/vorbis.h>
#include <uf/ext/oal/oal.h>
#endif #endif
/* /*
UF_API uf::Audio::Audio( const std::string& filename ) : m_filename(filename) { UF_API uf::Audio::Audio( const std::string& filename ) : m_filename(filename) {
@ -20,11 +21,19 @@ UF_API uf::Audio::Audio( const uf::Audio& copy ) :
{ {
} }
*/ */
uf::Audio::~Audio() {
this->destroy();
}
bool UF_API uf::Audio::initialized() { bool UF_API uf::Audio::initialized() {
if ( !this->m_source.getIndex() ) return false; if ( !this->m_source.getIndex() ) return false;
if ( !this->m_buffer.getIndex() ) return false; if ( !this->m_buffer.getIndex() ) return false;
return true; return true;
} }
void UF_API uf::Audio::destroy() {
this->m_source.destroy();
this->m_buffer.destroy();
}
bool UF_API uf::Audio::playing() { bool UF_API uf::Audio::playing() {
if ( !this->initialized() ) return false; if ( !this->initialized() ) return false;
if ( !this->m_source.playing() ) return false; if ( !this->m_source.playing() ) return false;
@ -42,22 +51,24 @@ void UF_API uf::Audio::load( const std::string& filename ) { if ( filename != ""
frequency = vorbis.getFrequency(); frequency = vorbis.getFrequency();
this->m_duration = vorbis.getDuration(); this->m_duration = vorbis.getDuration();
this->m_buffer.generate(); this->m_buffer.generate(); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.generate(); this->m_source.generate(); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency ); this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "BUFFER", std::vector<ALint>{ this->m_buffer.getIndex() } ); this->m_source.source( "BUFFER", std::vector<ALint>{ this->m_buffer.getIndex() } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "PITCH", std::vector<ALfloat>{ 1 } ); this->m_source.source( "PITCH", std::vector<ALfloat>{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "GAIN", std::vector<ALfloat>{ 1 } ); this->m_source.source( "GAIN", std::vector<ALfloat>{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__);
this->m_source.source( "LOOPING", std::vector<ALint>{ AL_FALSE } ); this->m_source.source( "LOOPING", std::vector<ALint>{ AL_FALSE } ); ext::oal.checkError(__FUNCTION__, __LINE__);
} }
} }
void UF_API uf::Audio::play() { void UF_API uf::Audio::play() {
if ( !this->initialized() ) return;
this->m_source.play(); this->m_source.play();
} }
void UF_API uf::Audio::stop() { void UF_API uf::Audio::stop() {
if ( !this->initialized() ) return;
this->m_source.stop(); this->m_source.stop();
} }
const std::string& UF_API uf::Audio::getFilename() const { const std::string& UF_API uf::Audio::getFilename() const {
@ -66,64 +77,64 @@ const std::string& UF_API uf::Audio::getFilename() const {
float uf::Audio::getDuration() const { float uf::Audio::getDuration() const {
return this->m_duration; return this->m_duration;
} }
#include <uf/ext/oal/oal.h>
ALfloat UF_API uf::Audio::getTime() { ALfloat UF_API uf::Audio::getTime() {
if ( this->playing() ) return 0; if ( !this->playing() ) return 0;
ALfloat pos; ALfloat pos;
alGetSourcef(this->m_source.getIndex(), AL_SEC_OFFSET, &pos ); ext::oal.checkError(__FUNCTION__, __LINE__); alGetSourcef(this->m_source.getIndex(), AL_SEC_OFFSET, &pos ); ext::oal.checkError(__FUNCTION__, __LINE__);
return pos; return pos;
} }
void UF_API uf::Audio::setTime( ALfloat pos ) { void UF_API uf::Audio::setTime( ALfloat pos ) {
if ( this->playing() ) return; if ( !this->initialized() ) return;
this->m_source.source("SEC_OFFSET", std::vector<ALfloat>{ pos } ); this->m_source.source("SEC_OFFSET", std::vector<ALfloat>{ pos } );
} }
ALfloat UF_API uf::Audio::getPitch() { ALfloat UF_API uf::Audio::getPitch() {
if ( this->playing() ) return 0; if ( !this->initialized() ) return 0;
ALfloat pitch; ALfloat pitch;
alGetSourcef(this->m_source.getIndex(), AL_PITCH, &pitch ); ext::oal.checkError(__FUNCTION__, __LINE__); alGetSourcef(this->m_source.getIndex(), AL_PITCH, &pitch ); ext::oal.checkError(__FUNCTION__, __LINE__);
return pitch; return pitch;
} }
void UF_API uf::Audio::setPitch( ALfloat pitch ) { void UF_API uf::Audio::setPitch( ALfloat pitch ) {
if ( this->playing() ) return; if ( !this->initialized() ) return;
this->m_source.source("PITCH", std::vector<ALfloat>{ pitch } ); this->m_source.source("PITCH", std::vector<ALfloat>{ pitch } );
} }
ALfloat UF_API uf::Audio::getGain() { ALfloat UF_API uf::Audio::getGain() {
if ( this->playing() ) return 0; if ( !this->initialized() ) return 0;
ALfloat gain; ALfloat gain;
alGetSourcef(this->m_source.getIndex(), AL_GAIN, &gain ); ext::oal.checkError(__FUNCTION__, __LINE__); alGetSourcef(this->m_source.getIndex(), AL_GAIN, &gain ); ext::oal.checkError(__FUNCTION__, __LINE__);
return gain; return gain;
} }
void UF_API uf::Audio::setGain( ALfloat gain ) { void UF_API uf::Audio::setGain( ALfloat gain ) {
if ( this->playing() ) return; if ( !this->initialized() ) return;
this->m_source.source("GAIN", std::vector<ALfloat>{ gain } ); this->m_source.source("GAIN", std::vector<ALfloat>{ gain } );
} }
ALfloat UF_API uf::Audio::getRolloffFactor() { ALfloat UF_API uf::Audio::getRolloffFactor() {
if ( this->playing() ) return 0; if ( !this->initialized() ) return 0;
ALfloat rolloffFactor; ALfloat rolloffFactor;
alGetSourcef(this->m_source.getIndex(), AL_ROLLOFF_FACTOR, &rolloffFactor ); ext::oal.checkError(__FUNCTION__, __LINE__); alGetSourcef(this->m_source.getIndex(), AL_ROLLOFF_FACTOR, &rolloffFactor ); ext::oal.checkError(__FUNCTION__, __LINE__);
return rolloffFactor; return rolloffFactor;
} }
void UF_API uf::Audio::setRolloffFactor( ALfloat rolloffFactor ) { void UF_API uf::Audio::setRolloffFactor( ALfloat rolloffFactor ) {
if ( this->playing() ) return; if ( !this->initialized() ) return;
this->m_source.source("ROLLOFF_FACTOR", std::vector<ALfloat>{ rolloffFactor } ); this->m_source.source("ROLLOFF_FACTOR", std::vector<ALfloat>{ rolloffFactor } );
} }
ALfloat UF_API uf::Audio::getMaxDistance() { ALfloat UF_API uf::Audio::getMaxDistance() {
if ( this->playing() ) return 0; if ( !this->initialized() ) return 0;
ALfloat maxDistance; ALfloat maxDistance;
alGetSourcef(this->m_source.getIndex(), AL_MAX_DISTANCE, &maxDistance ); ext::oal.checkError(__FUNCTION__, __LINE__); alGetSourcef(this->m_source.getIndex(), AL_MAX_DISTANCE, &maxDistance ); ext::oal.checkError(__FUNCTION__, __LINE__);
return maxDistance; return maxDistance;
} }
void UF_API uf::Audio::setMaxDistance( ALfloat maxDistance ) { void UF_API uf::Audio::setMaxDistance( ALfloat maxDistance ) {
if ( this->playing() ) return; if ( !this->initialized() ) return;
this->m_source.source("MAX_DISTANCE", std::vector<ALfloat>{ maxDistance } ); this->m_source.source("MAX_DISTANCE", std::vector<ALfloat>{ maxDistance } );
} }
void UF_API uf::Audio::setPosition( const pod::Vector3& position ) { void UF_API uf::Audio::setPosition( const pod::Vector3& position ) {
if ( !this->initialized() ) return;
this->m_source.source("POSITION", std::vector<ALfloat>{position.x, position.y, position.z} ); this->m_source.source("POSITION", std::vector<ALfloat>{position.x, position.y, position.z} );
} }
void UF_API uf::Audio::setOrientation( const pod::Quaternion<>& orientation ) { void UF_API uf::Audio::setOrientation( const pod::Quaternion<>& orientation ) {
@ -164,9 +175,9 @@ const uf::SoundEmitter::container_t& UF_API uf::SoundEmitter::get() const {
} }
void UF_API uf::SoundEmitter::cleanup( bool purge ) { void UF_API uf::SoundEmitter::cleanup( bool purge ) {
/* for ( auto& pair : this->m_container ) {
for ( uf::Audio& k : this->m_container ) { if ( !pair.second.playing() ) {
if ( !k.playing() ) this->m_container.erase(k); this->m_container.erase(pair.first);
}
} }
*/
} }

View File

@ -7,6 +7,19 @@
#include <fstream> #include <fstream>
#include <uf/utils/io/iostream.h> #include <uf/utils/io/iostream.h>
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif
std::string UF_API uf::io::absolute( const std::string& path ) {
char buff[FILENAME_MAX];
GetCurrentDir( buff, FILENAME_MAX );
return std::string(buff) + path;
}
std::string UF_API uf::io::filename( const std::string& str ) { std::string UF_API uf::io::filename( const std::string& str ) {
return str.substr( str.find_last_of('/') + 1 ); return str.substr( str.find_last_of('/') + 1 );
} }

View File

@ -54,7 +54,7 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) {
std::string thread = name; std::string thread = name;
if ( current > 0 ) thread += " " + std::to_string(current); if ( current > 0 ) thread += " " + std::to_string(current);
bool exists = uf::thread::has(thread); bool exists = uf::thread::has(thread);
auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true, false ); auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true );
if ( !exists ) { if ( !exists ) {
/* /*
pod.affinity = (current + 1) % threads; pod.affinity = (current + 1) % threads;
@ -66,7 +66,17 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) {
} }
return pod; return pod;
} }
void UF_API uf::thread::batchWorkers( const std::vector<pod::Thread::function_t>& functions, bool wait, const std::string& name ) {
std::vector<pod::Thread*> workers;
for ( auto& function : functions ) {
auto& worker = uf::thread::fetchWorker( name );
workers.emplace_back(&worker);
uf::thread::add( worker, function, true );
}
if ( wait )
for ( auto& worker : workers )
uf::thread::wait( *worker );
}
/* /*
void UF_API uf::thread::tick( pod::Thread& thread, const std::function<void()>& callback ) { void UF_API uf::thread::tick( pod::Thread& thread, const std::function<void()>& callback ) {
while ( thread.running ) { while ( thread.running ) {
@ -82,6 +92,7 @@ void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t&
if ( thread.mutex != NULL ) thread.mutex->unlock(); if ( thread.mutex != NULL ) thread.mutex->unlock();
} }
void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { if ( UF_THREAD_ANNOUNCE ) uf::iostream << "Bad Thread: " << thread.uid << " " << thread.name << "\n"; return; } //ops void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { if ( UF_THREAD_ANNOUNCE ) uf::iostream << "Bad Thread: " << thread.uid << " " << thread.name << "\n"; return; } //ops
/*
std::function<int()> temps = [&] { std::function<int()> temps = [&] {
int i = 0; int i = 0;
while ( !thread.temps.empty() ) { while ( !thread.temps.empty() ) {
@ -100,17 +111,40 @@ void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(u
} }
return i; return i;
}; };
if ( thread.mutex != NULL ) thread.mutex->lock(); if ( thread.mutex != NULL ) thread.mutex->lock();
temps(); temps();
consts(); consts();
if ( thread.mutex != NULL ) thread.mutex->unlock(); if ( thread.mutex != NULL ) thread.mutex->unlock();
*/
size_t temps = 0;
size_t consts = 0;
while ( !thread.temps.empty() ) {
auto& function = thread.temps.front();
if ( function ) function();
thread.temps.pop();
++temps;
}
for ( auto function : thread.consts ) {
function();
++consts;
}
thread.condition.notify_one();
} }
void UF_API uf::thread::wait( pod::Thread& thread ) { void UF_API uf::thread::wait( pod::Thread& thread ) {
if ( thread.mutex != NULL ) {
std::unique_lock<std::mutex> lock(*thread.mutex);
thread.condition.wait(lock, [&]{return thread.temps.empty();});
return;
}
while ( !thread.temps.empty() );
/*
if ( thread.mutex != NULL ) { if ( thread.mutex != NULL ) {
thread.mutex->lock(); thread.mutex->lock();
thread.mutex->unlock(); thread.mutex->unlock();
return;
} }
while ( !thread.temps.empty() );
*/
} }
const std::string& UF_API uf::thread::name( const pod::Thread& thread ) { const std::string& UF_API uf::thread::name( const pod::Thread& thread ) {

View File

@ -99,7 +99,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
float delta = metadata["light"]["fade"]["timer"].asFloat(); float delta = metadata["light"]["fade"]["timer"].asFloat();
delta = std::clamp( delta, 0.f, 1.f ); delta = std::clamp( delta, 0.f, 1.f );
if ( metadata["light"]["fade"]["power"].isNumeric() ) { if ( metadata["light"]["fade"]["power"].isNumeric() ) {
metadata["light"]["power"] = std::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta ); metadata["light"]["power"] = uf::math::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta );
} }
if ( metadata["light"]["fade"]["color"].isArray() ) { if ( metadata["light"]["fade"]["color"].isArray() ) {
pod::Vector3f fadeColor; { pod::Vector3f fadeColor; {

View File

@ -271,6 +271,29 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uint32_t maxLights = 32; uint32_t maxLights = 32;
} specializationConstants; } specializationConstants;
std::vector<uf::Entity*> entities;
{
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
}
for ( size_t _ = 0; _ < blitters.size(); ++_ ) { for ( size_t _ = 0; _ < blitters.size(); ++_ ) {
auto& blitter = *blitters[_]; auto& blitter = *blitters[_];
@ -284,7 +307,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
buffer = (uint8_t*) (void*) userdata; buffer = (uint8_t*) (void*) userdata;
len = userdata.data().len; len = userdata.data().len;
shader = &_; shader = &_;
// specializationConstants = _.specializationConstants.get<SpecializationConstant>();
specializationConstants = *((SpecializationConstant*) &_.specializationConstants[0]); specializationConstants = *((SpecializationConstant*) &_.specializationConstants[0]);
} }
@ -323,27 +345,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
} }
} }
{ {
std::vector<uf::Entity*> entities;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)]; UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) { for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
UniformDescriptor::Light& light = lights[i]; UniformDescriptor::Light& light = lights[i];
@ -353,6 +354,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
light.depthBias = 0; light.depthBias = 0;
} }
std::vector<VkImage> previousTextures;
for ( auto& texture : blitter.material.textures ) {
previousTextures.emplace_back(texture.image);
}
blitter.material.textures.clear(); blitter.material.textures.clear();
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) { for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
@ -390,7 +395,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uint8_t i = 0; uint8_t i = 0;
for ( auto& attachment : renderTarget.attachments ) { for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
// if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) continue; if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) continue;
auto& texture = blitter.material.textures.emplace_back(); auto& texture = blitter.material.textures.emplace_back();
texture.aliasAttachment(attachment); texture.aliasAttachment(attachment);
@ -399,9 +403,21 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
} }
} }
} }
size_t i = 0;
bool shouldUpdate = blitter.material.textures.size() != previousTextures.size();
while ( !shouldUpdate && i < blitter.material.textures.size() ) {
auto& texture = blitter.material.textures[i];
auto& previousTexture = previousTextures[i];
if ( texture.image != previousTexture ) shouldUpdate = true;
++i;
} }
// check if we actually do need to update our pipeline, to avoid the command buffer rebuild cost
if ( shouldUpdate ) {
blitter.getPipeline().update( blitter ); blitter.getPipeline().update( blitter );
}
}
shader->updateBuffer( (void*) buffer, len, 0, false ); shader->updateBuffer( (void*) buffer, len, 0, false );
} }
} }
} }

View File

@ -1,528 +0,0 @@
#include "behavior.h"
#include <uf/utils/hook/hook.h>
#include <uf/utils/time/time.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/userdata/userdata.h>
#include <uf/utils/graphic/mesh.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/window/window.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/utils/image/image.h>
#include <uf/engine/asset/asset.h>
#include "../../scenes/worldscape//battle.h"
#include "../../scenes/worldscape//.h"
#include <fstream>
#define PRINT_VECTOR2(v)\
std::cout << #v << ": " << v.x << ", " << v.y << std::endl;
namespace {
pod::Vector3f AXIS_OF_ROTATION = { 0, 0, 1 };
struct Bone {
std::string name = "";
std::string parent = "";
float length = 0;
pod::Vector2f position = { 0, 0 };
float rotation = 0;
};
struct AtlasPiece {
std::string name = "";
struct {
pod::Vector2f min = { 0, 0 };
pod::Vector2f max = { 0, 0 };
} uv;
struct {
pod::Vector2f topLeft = {-0.5f, 0.5f};
pod::Vector2f topRight = { 0.5f, 0.5f};
pod::Vector2f bottomLeft = {-0.5f, -0.5f};
pod::Vector2f bottomRight = { 0.5f, -0.5f};
} position;
pod::Vector2f scale = { 1, 1 };
pod::Vector2f size = { 0, 0 };
pod::Quaternion<> orientation = { 0, 0, 0, 1 };
float rotation = 0;
};
struct {
uf::Serializer animation;
uf::Serializer atlas;
uf::Serializer overrides;
} manifests;
struct {
std::unordered_map<std::string, Bone> skeleton;
std::unordered_map<std::string, AtlasPiece> attachments;
std::unordered_map<std::string, uf::Serializer> skins;
std::unordered_map<std::string, uf::Serializer> slots;
} maps;
float getRotation( const std::string& boneName, bool flatten = false, float start = 0 ) {
if ( manifests.overrides[boneName]["rotation"].isNumeric() ) {
return manifests.overrides[boneName]["rotation"].asFloat();
}
float rotation = start;
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return rotation;
}
Bone* bone = &maps.skeleton[boneName];
do {
rotation += bone->rotation;
if ( bone->parent == "" ) break;
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return rotation;
}
pod::Quaternion<> getOrientation( const std::string& boneName, bool flatten = false, float start = 0 ) {
float rotation = getRotation( boneName, flatten, start );
return uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
}
pod::Vector3f getPosition( const std::string& boneName, bool flatten = false ) {
if ( manifests.overrides[boneName]["position"].isArray() ) {
return pod::Vector3f{
manifests.overrides[boneName]["position"][0].asFloat(),
manifests.overrides[boneName]["position"][1].asFloat(),
0,
};
}
pod::Vector3f position = { 0, 0, 0 };
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return position;
}
Bone* bone = &maps.skeleton[boneName];
std::vector<pod::Vector2f> positions;
do {
if ( bone->parent == "" ) break;
float rotation = getRotation( bone->parent, flatten );
pod::Quaternion<> orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
position += uf::quaternion::rotate( orientation, pod::Vector3f{ bone->position.x, bone->position.y, 0 } );
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return position;
}
pod::Matrix4f getMatrix( const std::string& boneName, bool flatten = false, float start = 0 ) {
pod::Matrix4f matrix = uf::matrix::identity();
if ( start > 0.0f ) {
matrix = matrix * uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, start ) );
}
if ( maps.skeleton.count(boneName) < 0 ) {
std::cout << "Bone not in skeleton: " << boneName << std::endl;
return matrix;
}
Bone* bone = &maps.skeleton[boneName];
do {
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), {bone->position.x, bone->position.y, 0} );
pod::Matrix4f rotation = uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, bone->rotation ) );
matrix = matrix * translation * rotation;
if ( bone->parent == "" ) break;
bone = &maps.skeleton[bone->parent];
} while ( flatten );
return matrix;
}
uf::Serializer getSkin( const uf::Serializer& slot ) {
uf::Serializer json;
std::string name = slot["name"].asString();
std::string attachment = slot["attachment"].asString();
if ( !maps.skins["default"][name][attachment].isNull() ) json = maps.skins["default"][name][attachment];
else if ( !maps.skins["normal"][name][attachment].isNull() ) json = maps.skins["normal"][name][attachment];
return json;
}
}
EXT_BEHAVIOR_REGISTER_CPP(LahSpineBehavior)
#define this (&self)
void ext::LahSpineBehavior::initialize( uf::Object& self ) {
uf::Scene& scene = uf::scene::getCurrentScene();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
manifests.atlas.readFromFile(metadata["system"]["root"].asString() + "atlas.json");
manifests.animation.readFromFile(metadata["system"]["root"].asString() + "animation.json");
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
metadata["system"]["control"] = false;
if ( uf::io::extension(filename) != "png" ) return "false";
uf::Scene& scene = this->getRootParent<uf::Scene>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
const uf::Image* imagePointer = NULL;
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
if ( !imagePointer ) return "false";
uf::Image image = *imagePointer;
// test overrides
{
manifests.overrides = metadata["atlas"]["overrides"];
}
// assemble skeleton
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["bones"].size(); ++i ) {
auto& entry = manifest["bones"][i];
std::string name = entry["name"].asString();
auto& bone = maps.skeleton[name];
bone.name = name;
if ( entry["parent"].isString() ) bone.parent = entry["parent"].asString();
if ( entry["x"].isNumeric() ) bone.position.x = entry["x"].asFloat();
if ( entry["y"].isNumeric() ) bone.position.y = entry["y"].asFloat();
if ( entry["length"].isNumeric() ) bone.length = entry["length"].asFloat();
if ( entry["rotation"].isNumeric() ) bone.rotation = entry["rotation"].asFloat(); // * 3.14159f / 180.0f;
}
}
// create sprite attachments
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["skins"].size(); ++i ) {
std::string skinName = manifest["skins"][i]["name"].asString();
if ( skinName == "damage" ) continue;
maps.skins[skinName] = manifest["skins"][i]["attachments"];
}
}
// register slots
{
auto& manifest = manifests.animation;
for ( int i = 0; i < manifest["slots"].size(); ++i ) {
std::string slotName = manifest["slots"][i]["name"].asString();
maps.slots[slotName] = manifest["slots"][i];
}
}
// parse atlas
{
auto& manifest = manifests.atlas;
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
std::string name = it.key().asString();
pod::Vector2f sheetSize = { manifest["size"][0].asFloat(), manifest["size"][1].asFloat() };
pod::Vector2f xy = { manifest["pieces"][name]["xy"][0].asFloat(), manifest["pieces"][name]["xy"][1].asFloat() };
pod::Vector2f size = { manifest["pieces"][name]["size"][0].asFloat(), manifest["pieces"][name]["size"][1].asFloat() };
float rotation = 0.0f;
auto& piece = maps.attachments[name];
piece.size = size;
if ( manifest["pieces"][name]["rotate"].isNumeric() ) {
auto& rotation = piece.rotation;
auto& orientation = piece.orientation;
rotation = manifest["pieces"][name]["rotate"].asFloat(); // * 3.14159f / 180.0f;
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f );
pod::Vector3f rotated;
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
size.x = fabs(rotated.x);
size.y = fabs(rotated.y);
}
orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, (rotation + 90) * 3.14159f / 180.0f );
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } );
piece.size.x = fabs(rotated.x);
piece.size.y = fabs(rotated.y);
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topLeft.x, piece.position.topLeft.y, 0 } );
piece.position.topLeft.x = rotated.x;
piece.position.topLeft.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topRight.x, piece.position.topRight.y, 0 } );
piece.position.topRight.x = rotated.x;
piece.position.topRight.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomLeft.x, piece.position.bottomLeft.y, 0 } );
piece.position.bottomLeft.x = rotated.x;
piece.position.bottomLeft.y = rotated.y;
}
{
rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomRight.x, piece.position.bottomRight.y, 0 } );
piece.position.bottomRight.x = rotated.x;
piece.position.bottomRight.y = rotated.y;
}
}
piece.name = name;
piece.uv.min = ( xy ) / sheetSize;
piece.uv.max = ( xy + size ) / sheetSize;
piece.scale = size / sheetSize;
}
}
{
std::vector<std::string> whitelist = {};
for ( int i = 0; i < metadata["atlas"]["whitelist"].size(); ++i ) {
whitelist.emplace_back(metadata["atlas"]["whitelist"][i].asString());
}
auto& manifest = manifests.atlas;
for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) {
std::string name = it.key().asString();
if ( !whitelist.empty() && std::find( whitelist.begin(), whitelist.end(), name ) == whitelist.end() ) continue;
auto& child = uf::instantiator::instantiate<uf::Object>();
uf::instantiator::bind( "LahSpinePieceBehavior", child );
this->addChild(child);
child.initialize();
uf::Serializer payload;
payload["attachment"]["name"] = name;
payload["attachment"]["useMatrix"] = metadata["atlas"]["useMatrix"];
payload["filename"] = json["filename"];
child.queueHook("graphics:Assign.%UID%", payload);
metadata["attachments"][name] = child.getUid();
}
}
return "true";
});
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
this->queueHook("graphics:Assign.%UID%", event, 0.0f);
return "true";
});
}
void ext::LahSpineBehavior::tick( uf::Object& self ) {}
void ext::LahSpineBehavior::render( uf::Object& self ){
}
void ext::LahSpineBehavior::destroy( uf::Object& self ){}
#undef this
EXT_BEHAVIOR_REGISTER_CPP(LahSpinePieceBehavior)
#define this (&self)
void ext::LahSpinePieceBehavior::initialize( uf::Object& self ) {
uf::Scene& scene = uf::scene::getCurrentScene();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
metadata["system"]["control"] = false;
if ( uf::io::extension(filename) != "png" ) return "false";
uf::Scene& scene = this->getRootParent<uf::Scene>();
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
const uf::Image* imagePointer = NULL;
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
if ( !imagePointer ) return "false";
uf::Image image = *imagePointer;
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
metadata["attachment"] = json["attachment"];
metadata["color"][0] = 1;
metadata["color"][1] = 1;
metadata["color"][2] = 1;
metadata["color"][3] = 1;
std::string name = metadata["attachment"]["name"].asString();
auto& attachment = maps.attachments[name];
auto& slot = maps.slots[name];
// transform.scale = { attachment.scale.x, attachment.scale.y, 1 };
transform.scale = { 1.0f / 512.0f, 1.0f / 512.0f, 1 };
std::string boneName = slot["bone"].asString();
transform.position = getPosition( boneName, true );
transform.orientation = getOrientation( boneName, true );
std::cout << "\"" << name << "\": {\"position\": [ " << transform.position.x << ", " << transform.position.y << " ], \"rotation\": " << getRotation( name, true ) << " }," << std::endl;
transform.position *= transform.scale;
struct {
pod::Vector2f position;
pod::Vector2f uv;
} topLeft, topRight, bottomLeft, bottomRight;
{
topLeft.position = attachment.size * attachment.position.topLeft;
topRight.position = attachment.size * attachment.position.topRight;
bottomLeft.position = attachment.size * attachment.position.bottomLeft;
bottomRight.position = attachment.size * attachment.position.bottomRight;
}
{
topLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.min.y };
topRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.min.y };
bottomLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.max.y };
bottomRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.max.y };
}
mesh.vertices = {
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
{ { topRight.position.x, topRight.position.y, 0.0f }, topRight.uv,{ 0.0f, 0.0f, -1.0f } },
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
{ { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } },
{ { bottomLeft.position.x, bottomLeft.position.y, 0.0f }, bottomLeft.uv, { 0.0f, 0.0f, -1.0f } },
{ { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } },
};
{
std::cout << name << ". Slot: " << slot << std::endl;
auto skin = getSkin( slot );
struct WeightedVertex {
int boneId;
float weight;
pod::Vector2f position;
};
struct SkinnedVertex {
std::vector<WeightedVertex> weights;
pod::Vector2f position;
pod::Vector2f uv;
};
std::vector<SkinnedVertex> skinnedVertices;
std::cout << name << ", Vertices?:\n";
for ( int i = 0; i < skin["vertices"].size(); ) {
int read = skin["vertices"][i++].asInt();
auto& skinVertex = skinnedVertices.emplace_back();
for ( int j = 0; j < read; ++j ) {
auto& weightedVertex = skinVertex.weights.emplace_back();
weightedVertex.boneId = skin["vertices"][i++].asInt();
weightedVertex.position.x = skin["vertices"][i++].asFloat();
weightedVertex.position.y = skin["vertices"][i++].asFloat();
weightedVertex.weight = skin["vertices"][i++].asFloat();
}
}
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
auto& skinVertex = skinnedVertices.at(i);
skinVertex.uv.x = skin["uvs"][(i*2+0)].asFloat();
skinVertex.uv.y = skin["uvs"][(i*2+1)].asFloat();
// average
for ( auto& weightedVertex : skinVertex.weights ) {
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
auto bonePosition = getPosition( boneName, true );
auto boneOrientation = getOrientation( boneName, true );
bonePosition = uf::quaternion::rotate( boneOrientation, bonePosition );
auto rotatedVertex = uf::quaternion::rotate( boneOrientation, pod::Vector3f{ weightedVertex.position.x, weightedVertex.position.y, 0 } );
skinVertex.position.x += (rotatedVertex.x + bonePosition.x) * weightedVertex.weight;
skinVertex.position.y += (rotatedVertex.y + bonePosition.y) * weightedVertex.weight;
// wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
}
}
for ( int i = 0; i < skinnedVertices.size(); ++i ) {
auto& skinVertex = skinnedVertices.at(i);
std::cout << "Index " << i << ":\n";
for ( auto& weightedVertex : skinVertex.weights ) {
std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString();
std::cout << "\tPosition: " << weightedVertex.position.x << ", " << weightedVertex.position.y << " | Bone ID: " << weightedVertex.boneId << " | Bone Name: " << boneName << " | Weight: " << weightedVertex.weight << "\n";
}
std::cout << "\tUV: " << skinVertex.uv.x << ", " << skinVertex.uv.y << "\n";
std::cout << "\tWeighted Position: " << skinVertex.position.x << ", " << skinVertex.position.y << "\n";
}
std::cout << std::endl;
std::cout << name << ", Triangles:\n";
mesh.vertices.clear();
for ( auto i = 0; i < skin["triangles"].size(); ) {
std::cout << "Triangle:\n";
for ( int j = 0; j < 3; ++j ) {
int index = skin["triangles"][i++].asInt();
auto& skinVertex = skinnedVertices.at(index);
struct {
pod::Vector2f interp;
} position, uv;
uv.interp.x = std::lerp( attachment.uv.min.x, attachment.uv.max.x, skinVertex.uv.x );
uv.interp.y = std::lerp( attachment.uv.min.y, attachment.uv.max.y, skinVertex.uv.y );
// uv.interp = skinVertex.uv;
position.interp.x = (uv.interp.x - 0.5f) * attachment.size.x;
position.interp.y = (uv.interp.y - 0.5f) * attachment.size.y;
std::cout << "\tIndex: " << index << "\tUV: " << uv.interp.x << ", " << uv.interp.y << "\tPosition: " << position.interp.x << ", " << position.interp.y << "\n";
auto& vertex = mesh.vertices.emplace_back();
// vertex.position.x = position.interp.x;
// vertex.position.y = position.interp.y;
vertex.position.x = skinVertex.position.x;
vertex.position.y = skinVertex.position.y;
vertex.position.z = 0;
vertex.uv.x = uv.interp.x;
vertex.uv.y = 1.0f - uv.interp.y;
vertex.normal = { 0, 0, -1 };
}
std::cout << std::endl;
}
/*
std::cout << name << ", Triangles:\n";
for ( auto i = 0; i < skin["triangles"].size(); i += 3 ) {
// std::cout << "\t" << skin["triangles"][i+0].asInt() << " " << skin["triangles"][i+1].asInt() << " " << skin["triangles"][i+2].asInt() << std::endl;
std::cout << "\t" << skin["uvs"][skin["triangles"][i+0].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+1].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+2].asInt()].asFloat()
}
*/
std::cout << name << ", "
<< "UVs: " << skin["uvs"].size() << ", "
<< "Positions: " << skin["vertices"].size() << ", "
<< "Triangles: " << skin["triangles"].size() << ", "
<< "Edges: " << skin["edges"].size() << ", "
<< "Hull: " << skin["hull"]
<< std::endl;
}
graphic.initialize( "Gui" );
graphic.initializeGeometry( mesh );
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( image );
graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
metadata["system"]["control"] = true;
metadata["system"]["loaded"] = true;
return "true";
});
}
void ext::LahSpinePieceBehavior::tick( uf::Object& self ) {}
void ext::LahSpinePieceBehavior::render( uf::Object& self ){
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( !metadata["system"]["loaded"].asBool() ) return;
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
auto& mesh = this->getComponent<uf::Mesh>();
auto& scene = uf::scene::getCurrentScene();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& camera = scene.getController().getComponent<uf::Camera>();
if ( !graphic.initialized ) return;
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
auto translation = uf::matrix::translate( uf::matrix::identity(), transform.position );
auto rotation = uf::quaternion::matrix( transform.orientation );
auto scale = uf::matrix::scale( uf::matrix::identity(), transform.scale );
auto model = translation * rotation * scale;
std::string name = metadata["attachment"]["name"].asString();
auto& attachment = maps.attachments[name];
auto bone = getMatrix( name, true );
uniforms.matrices.model = metadata["attachment"]["useMatrix"].asBool() ? bone : model;
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
}
uniforms.color[0] = metadata["color"][0].asFloat();
uniforms.color[1] = metadata["color"][1].asFloat();
uniforms.color[2] = metadata["color"][2].asFloat();
uniforms.color[3] = metadata["color"][3].asFloat();
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
};
}
void ext::LahSpinePieceBehavior::destroy( uf::Object& self ){}
#undef this

View File

@ -1,25 +0,0 @@
#pragma once
#include <uf/config.h>
#include <uf/ext/ext.h>
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
namespace ext {
class EXT_API LahSpineBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );
static void destroy( uf::Object& );
};
class EXT_API LahSpinePieceBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );
static void destroy( uf::Object& );
};
}

View File

@ -11,8 +11,12 @@ EXT_BEHAVIOR_REGISTER_CPP(StaticEmitterBehavior)
#define this ((uf::Object*) &self) #define this ((uf::Object*) &self)
void ext::StaticEmitterBehavior::initialize( uf::Object& self ) { void ext::StaticEmitterBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>(); auto& metadata = this->getComponent<uf::Serializer>();
// this->addHook( "system:Load.Finished.%UID%", [&](const std::string& event)->std::string{
// uf::Serializer json = event;
auto* hud = this->loadChildPointer("/hud.json", true); auto* hud = this->loadChildPointer("/hud.json", true);
metadata["hud"]["uid"] = hud->getUid(); metadata["hud"]["uid"] = hud->getUid();
// return "true";
// });
} }
void ext::StaticEmitterBehavior::tick( uf::Object& self ) { void ext::StaticEmitterBehavior::tick( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();

View File

@ -825,7 +825,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
// graphic.descriptor.indices = 0; // graphic.descriptor.indices = 0;
graphic.initializeGeometry( mesh ); graphic.initializeGeometry( mesh );
graphic.getPipeline().update( graphic ); graphic.getPipeline().update( graphic );
uf::renderer::rebuild = true; // uf::renderer::rebuild = true;
/* /*
graphic.destroy(); graphic.destroy();

View File

@ -253,9 +253,8 @@ void EXT_API ext::initialize() {
uf::renderer::initialize(); uf::renderer::initialize();
} }
/* */ { /* */ {
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true ); pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false );
// pod::Thread& threadAux = uf::thread::has("Aux") ? uf::thread::get("Aux") : uf::thread::create( "Aux", true, false ); pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true );
pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
} }
/* Discord */ if ( ::config["engine"]["ex"]["discord"]["enabled"].asBool() ) { /* Discord */ if ( ::config["engine"]["ex"]["discord"]["enabled"].asBool() ) {

View File

@ -89,20 +89,22 @@ void ext::RayTracingSceneBehavior::tick( uf::Object& self ) {
alignas(16) pod::Vector4f ambient; alignas(16) pod::Vector4f ambient;
struct { struct {
alignas(8) pod::Vector2f range; alignas(8) pod::Vector2f range;
alignas(8) pod::Vector2f padding;
alignas(16) pod::Vector4f color; alignas(16) pod::Vector4f color;
} fog; } fog;
struct Light { struct Light {
alignas(16) pod::Vector4f position; alignas(16) pod::Vector4f position;
alignas(16) pod::Vector4f color; alignas(16) pod::Vector4f color;
alignas(8) pod::Vector2i type; alignas(8) pod::Vector2i type;
alignas(8) pod::Vector2i padding;
alignas(16) pod::Matrix4f view; alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection; alignas(16) pod::Matrix4f projection;
} lights; } lights;
}; };
struct SpecializationConstant { struct SpecializationConstant {
uint32_t eyes = 2;
uint32_t maxLights = 16; uint32_t maxLights = 16;
uint32_t eyes = 2;
} specializationConstants; } specializationConstants;
auto& shader = renderMode.compute.material.shaders.front(); auto& shader = renderMode.compute.material.shaders.front();