Commit for 2022.06.12 17-21-07.7z

This commit is contained in:
mrq 2022-06-12 17:21:00 -05:00
parent a9f5a56366
commit e38c08ff85
76 changed files with 1520 additions and 1838 deletions

View File

@ -1,14 +1,18 @@
ARCH = win64
CC = $(shell cat "./bin/exe/default.config")
ARCH = $(shell cat "./makefiles/default/arch")
CC = $(shell cat "./makefiles/default/cc")
RENDERER = $(shell cat "./makefiles/default/renderer")
TARGET_NAME = program
TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll
RENDERER = vulkan
PREFIX = $(ARCH).$(CC)
include makefiles/$(PREFIX).make
.PHONY: $(ARCH)-$(CC)
PREFIX = $(ARCH).$(CC).$(RENDERER)
PREFIX_PATH = $(ARCH)/$(CC)/$(RENDERER)
.PHONY: $(PREFIX)
@echo "Setting defaults: $(ARCH).$(CC).$(RENDERER)"
.FORCE:
@ -22,6 +26,7 @@ ENGINE_LIB_DIR += ./engine/lib
EXT_SRC_DIR += ./ext
CLIENT_SRC_DIR += ./client
UF_LIBS +=
EXT_LIBS +=
FLAGS +=
@ -38,15 +43,14 @@ EXT_LIB_NAME += ext
#VULKAN_SDK_PATH += /c/VulkanSDK/1.3.204.1/
VULKAN_SDK_PATH += /c/VulkanSDK/1.3.211.0/
#GLSLC += $(VULKAN_SDK_PATH)/Bin/glslangValidator
GLSLC += $(VULKAN_SDK_PATH)/Bin/glslc
SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin/spirv-opt
# Base Engine's DLL
INC_DIR += $(ENGINE_INC_DIR)/$(ARCH)/$(CC)
LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH)
INC_DIR += $(ENGINE_INC_DIR)
LIB_DIR += $(ENGINE_LIB_DIR)
INCS += -I$(ENGINE_INC_DIR) -I$(INC_DIR) -I./dep/ #-I/mingw64/include
LIBS += -L$(ENGINE_LIB_DIR) -L$(LIB_DIR) -L$(LIB_DIR)/$(CC)
LIBS += -L$(ENGINE_LIB_DIR) -L$(LIB_DIR) -L$(LIB_DIR)/$(ARCH) -L$(LIB_DIR)/$(PREFIX_PATH)
LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
DEPS +=
@ -55,6 +59,7 @@ ifneq (,$(findstring win64,$(ARCH)))
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype curl luajit reactphysics meshoptimizer xatlas simd ctti gltf # ncurses openvr draco discord bullet ultralight-ux
FLAGS +=
DEPS += -lgdi32
LINKS += -Wl,-subsystem,windows
else ifneq (,$(findstring dreamcast,$(ARCH)))
REQ_DEPS += simd opengl gldc json:nlohmann reactphysics png zlib ctti # lua ogg openal aldc gltf freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
endif
@ -206,35 +211,34 @@ endif
SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp) $(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_DLL += $(patsubst %.cpp,%.$(PREFIX).o,$(SRCS_DLL))
BASE_DLL += lib$(LIB_NAME)
IM_DLL += $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a
EX_DLL += $(BIN_DIR)/exe/lib/$(ARCH)/$(CC)/$(BASE_DLL).$(TARGET_LIB_EXTENSION)
IM_DLL += $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a
EX_DLL += $(BIN_DIR)/exe/lib/$(PREFIX_PATH)/$(BASE_DLL).$(TARGET_LIB_EXTENSION)
# External Engine's DLL
EXT_INC_DIR += $(INC_DIR)
EXT_LB_FLAGS += $(LIB_DIR)
EXT_DEPS += -l$(LIB_NAME) $(DEPS)
EXT_LINKS += $(UF_LIBS) $(EXT_LIBS) $(EXT_DEPS)
#-Wl,-subsystem,windows
EXT_LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH)
EXT_INCS += -I$(ENGINE_INC_DIR) -I$(EXT_INC_DIR) -I$(VULKAN_SDK_PATH)/include -I/mingw64/include
EXT_LIBS += -L$(ENGINE_LIB_DIR) -L$(EXT_LIB_DIR) -L$(EXT_LIB_DIR)/$(CC) -L$(VULKAN_SDK_PATH)/Lib -L/mingw64/lib
EXT_INCS += -I$(ENGINE_INC_DIR) -I$(EXT_INC_DIR) -I/mingw64/include
EXT_LIBS += -L$(ENGINE_LIB_DIR) -L$(EXT_LIB_DIR) -L$(EXT_LIB_DIR)/$(ARCH) -L$(EXT_LIB_DIR)/$(PREFIX_PATH) -L/mingw64/lib
SRCS_EXT_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_DLL += $(patsubst %.cpp,%.$(PREFIX).o,$(SRCS_EXT_DLL))
BASE_EXT_DLL += lib$(EXT_LIB_NAME)
EXT_IM_DLL += $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a
EXT_EX_DLL += $(BIN_DIR)/exe/lib/$(ARCH)/$(CC)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION)
EXT_IM_DLL += $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a
EXT_EX_DLL += $(BIN_DIR)/exe/lib/$(PREFIX_PATH)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION)
# Client EXE
SRCS += $(wildcard $(CLIENT_SRC_DIR)/*.cpp) $(wildcard $(CLIENT_SRC_DIR)/*/*.cpp)
OBJS += $(patsubst %.cpp,%.$(PREFIX).o,$(SRCS))
TARGET += $(BIN_DIR)/exe/$(TARGET_NAME).$(CC).$(TARGET_EXTENSION)
TARGET += $(BIN_DIR)/exe/$(TARGET_NAME).$(PREFIX).$(TARGET_EXTENSION)
# Shaders
SRCS_SHADERS += $(wildcard bin/data/shaders/*.glsl) $(wildcard bin/data/shaders/*/*.glsl) $(wildcard bin/data/shaders/*/*/*.glsl)
TARGET_SHADERS += $(patsubst %.glsl,%.spv,$(SRCS_SHADERS))
ifneq (,$(findstring dreamcast,$(ARCH)))
#$(ARCH): $(EX_DLL) $(EXT_EX_DLL) $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
$(ARCH): $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
#$(PREFIX): $(EX_DLL) $(EXT_EX_DLL) $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
$(PREFIX): $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
SRCS_DLL = $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp)
OBJS_DLL = $(patsubst %.cpp,%.$(PREFIX).o,$(SRCS_DLL))
@ -245,17 +249,17 @@ DEPS += -lkallisti -lc -lm -lgcc -lstdc++ # -l$(LIB_NAME) -l$(EXT_LIB_NAME)
%.$(PREFIX).o: %.cpp
$(CXX) $(FLAGS) $(INCS) -c $< -o $@
$(EX_DLL): FLAGS += -DUF_EXPORTS -DJSON_DLL_BUILD
$(EX_DLL): FLAGS += -DUF_EXPORTS
$(EX_DLL): $(OBJS_DLL)
$(KOS_AR) cru $@ $^
$(KOS_RANLIB) $@
cp $@ $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_DLL).a
cp $@ $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_DLL).a
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS -DJSON_DLL_BUILD
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS
$(EXT_EX_DLL): $(OBJS_EXT_DLL)
$(KOS_AR) cru $@ $^
$(KOS_RANLIB) $@
cp $@ $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_EXT_DLL).a
cp $@ $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_EXT_DLL).a
./bin/dreamcast/romdisk.img:
$(KOS_GENROMFS) -f ./bin/dreamcast/romdisk.img -d ./bin/dreamcast/romdisk/ -v
@ -274,35 +278,35 @@ cdi:
cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME)
else
$(ARCH): $(EX_DLL) $(TARGET) $(TARGET_SHADERS)
$(PREFIX): $(EX_DLL) $(TARGET) $(TARGET_SHADERS)
%.$(PREFIX).o: %.cpp
$(CXX) $(FLAGS) $(INCS) -c $< -o $@
$(EX_DLL): FLAGS += -DUF_EXPORTS -DEXT_EXPORTS -DJSON_DLL_BUILD
#$(EX_DLL): FLAGS += -DUF_EXPORTS -DJSON_DLL_BUILD
$(EX_DLL): FLAGS += -DUF_EXPORTS -DEXT_EXPORTS
#$(EX_DLL): FLAGS += -DUF_EXPORTS
$(EX_DLL): $(OBJS_DLL)
$(CXX) -shared -o $(EX_DLL) -Wl,--out-implib=$(IM_DLL) $(OBJS_DLL) $(LIBS) $(INCS) $(LINKS)
cp $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_DLL).a
$(CXX) $(FLAGS) -shared -o $(EX_DLL) -Wl,--out-implib=$(IM_DLL) $(OBJS_DLL) $(LIBS) $(INCS) $(LINKS)
cp $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_DLL).a
@echo -n $(ARCH) > "./bin/exe/default/arch"
@echo -n $(CC) > "./bin/exe/default/cc"
@echo -n $(RENDERER) > "./bin/exe/default/renderer"
@echo "Setting defaults: $(ARCH).$(CC).$(RENDERER)"
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS -DJSON_DLL_BUILD
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS
$(EXT_EX_DLL): $(OBJS_EXT_DLL)
$(CXX) -shared -o $(EXT_EX_DLL) -Wl,--out-implib=$(EXT_IM_DLL) $(OBJS_EXT_DLL) $(EXT_LIBS) $(EXT_INCS) $(EXT_LINKS)
cp $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(ARCH)/$(CC)/$(BASE_EXT_DLL).a
cp $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(PREFIX_PATH)/$(BASE_EXT_DLL).a
$(TARGET): $(OBJS)
$(CXX) $(FLAGS) $(OBJS) $(LIBS) $(INCS) $(LINKS) -l$(LIB_NAME) -o $(TARGET)
# $(CXX) $(FLAGS) $(OBJS) $(LIBS) $(INCS) $(LINKS) -l$(LIB_NAME) -o $(TARGET)
# $(CXX) $(FLAGS) $(OBJS) $(LIBS) $(INCS) $(LINKS) -l$(LIB_NAME) -l$(EXT_LIB_NAME) -o $(TARGET)
endif
%.spv: %.glsl
$(GLSLC) -std=450 -o $@ $<
$(SPV_OPTIMIZER) --preserve-bindings --preserve-spec-constants -O $@ -o $@
ifneq (,$(findstring dreamcast,$(ARCH)))
clean:
@-rm $(EX_DLL)
@-rm $(EXT_EX_DLL)
@ -312,31 +316,26 @@ clean:
@-rm -f $(OBJS_EXT_DLL)
@-rm -f $(OBJS)
ifneq (,$(findstring dreamcast,$(ARCH)))
@-rm ./bin/dreamcast/build/*
@-rm ./bin/dreamcast/romdisk.*
@-rm ./bin/dreamcast/$(TARGET_NAME).*
clean-zips:
@-find ./bin/data/ -name "*.gz" -type f -delete
endif
run:
ifneq (,$(findstring dreamcast,$(ARCH)))
$(KOS_EMU) ./bin/dreamcast/$(TARGET_NAME).cdi
else
clean:
@-rm $(EX_DLL)
@-rm $(EXT_EX_DLL)
@-rm $(TARGET)
@-rm -f $(OBJS_DLL)
@-rm -f $(OBJS_EXT_DLL)
@-rm -f $(OBJS)
@echo -n $(ARCH) > "./bin/exe/default/arch"
@echo -n $(CC) > "./bin/exe/default/cc"
@echo -n $(RENDERER) > "./bin/exe/default/renderer"
@echo "Setting defaults: $(ARCH).$(CC).$(RENDERER)"
./program.sh
endif
clean-zips:
@-find ./bin/data/ -name "*.gz" -type f -delete
run:
./program.sh
endif
clean-uf:
@-rm $(EX_DLL)
@-rm -f $(OBJS_DLL)
@ -356,6 +355,8 @@ clean-shaders:
backup:
make ARCH=dreamcast clean
make CC=gcc clean
make CC=clang clean
make CC=gcc RENDERER=opengl clean
make CC=gcc RENDERER=vulkan clean
make CC=clang RENDERER=opengl clean
make CC=clang RENDERER=vulkan clean
$(7Z) a -r ../misc/backups/$(shell date +"%Y.%m.%d\ %H-%M-%S").7z .

View File

@ -5,20 +5,20 @@
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": true },
"lights": { "enabled": true,
"useLightmaps": false,
"max": 32
"useLightmaps": true,
"max": 16
},
"shadows": {
"enabled": true,
"update": 3,
"max": 6,
"samples": 2,
"update": 2,
"max": 8,
"samples": 1,
"experimental mode": 1
},
"textures": {
"max": {
"2D": 1024,
"cube": 128,
"2D": 256,
"cube": 32,
"3D": 1
}
},
@ -26,9 +26,9 @@
"limiter": 1,
"size": 128,
"dispatch": 8,
"cascades": 4,
"cascades": 3,
"cascadePower": 3,
"granularity": 8,
"granularity": 12,
"voxelizeScale": 1,
"occlusionFalloff": 2,
"shadows": 0,
@ -52,10 +52,11 @@
"filters": [
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
"MessageID = 0x23e43bb7" // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
"MessageID = 0x23e43bb7", // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
"MessageID = 0x71500fba" // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
// "MessageID = 0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
// "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
// "MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197 (hacky bloom-shit)
// "MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973 (hacky bloom-shit)
@ -66,26 +67,23 @@
]
},
"framebuffer": {
"size": 1,
// "size": [ 640, 480, "NEAREST" ],
// "size": [ 1280, 720 ],
// "size": [ 960, 540 ],
// "size": [ 640, 480 ],
"msaa": 1
"msaa": 1,
"size": 1
// "size": [ 640, 480, "NEAREST" ]
// "size": [ 1280, 720 ]
// "size": [ 960, 540 ]
// "size": [ 640, 480 ]
},
"gpu": "auto",
"experimental": {
"rebuild on tick begin": false,
"wait on render end": false,
"individual pipelines": true,
"multithreaded command recording": true,
"multithreaded command rendering": false,
"deferred mode": "",
"deferred reconstruct position": true,
"deferred alias output to swapchain": false,
"batch queue submissions": true,
"dedicated thread": false
},
"invariant": {},
"pipelines": {
"vsync": false,
"hdr": false,
"vxgi": true,
"deferred sampling": true,
"culling": true,
"bloom": false
},
@ -129,17 +127,7 @@
"opengl": {
"validation": { "enabled": true },
"framebuffer": { "size": 1, "msaa": 1 },
"experimental": {
"rebuild on tick begin": false,
"wait on render end": false,
"individual pipelines": true,
"multithreaded command recording": false, //
"multithreaded command rendering": false,
"deferred mode": "",
// "deferred mode": "deferredSampling",
"deferred reconstruct position": true,
"deferred alias output to swapchain": true,
"hdr": false,
"pipelines": {
"culling": true
},
"formats": {
@ -227,13 +215,13 @@
"framerate": "auto"
},
"threads": {
"workers" : "auto", // "async"
"workers" : "auto",
"frame limiter": "auto"
},
"debug": {
"framerate": {
"print": true,
"every": 1
"every": 2
},
"garbage collection": {
"enabled": true,
@ -253,7 +241,7 @@
"window" : {
"terminal" : {
"ncurses" : false,
"visible" : true
"visible" : false
},
"keyboard" : {
"repeat" : false
@ -261,9 +249,10 @@
"cursor" : {
"visible" : true,
"center" : false,
"sensitivity": [ 1, 1 ]
"sensitivity": [ 1.25, 1.25 ],
"smoothing": [ 10, 10 ]
},
"mode" : "windowed", // fullscreen, borderless, windowed
"mode" : "borderless", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png",
"size" : [ 1920, 1080 ],
// "size" : [ 1280, 720 ],

View File

@ -3,8 +3,8 @@
"type": "Gui",
"ignore": false,
"assets": [
"./scripts/menu.lua",
"./textures/menu.png"
"./textures/menu.png",
"./scripts/menu.lua"
],
"transform": {
"position": [ 0, 0, 0 ],

View File

@ -24,7 +24,7 @@
"precision": 4,
"combined": false,
"encode buffers": true,
"unwrap": false,
"unwrap": true,
"optimize": "tagged",
"quit": true,
"mesh": {
@ -43,7 +43,7 @@
"useInputMeshUvs": true,
"maxIterations": 8,
// "maxChartSize": 0,
// "padding": 0,
"padding": 4,
// "texelsPerUnit": 0,
"bilinear": true,
"blockAlign": true,

View File

@ -2,7 +2,7 @@
"import": "/model.json",
"assets": [
// { "filename": "./craeture.json", "delay": 1 },
{ "filename": "./test.json", "delay": 1 },
// { "filename": "./test.json", "delay": 1 },
// { "filename": "./models/tiny_msci.glb" }
{ "filename": "./models/tiny_msci/graph.json" }

View File

@ -16,6 +16,7 @@
"scaling": "relative",
"world": true,
"cull mode": "none",
"color": [ 1, 0, 1, 1 ],
"text settings": {
"scale": 8,
"font": "Coolvetica.ttf",

View File

@ -1,12 +1,12 @@
{
"engine": {
"scenes": {
"start": "McDonalds",
"start": "SS2",
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": false },
"lights": { "enabled": false,
"useLightmaps": true,
"max": 2
"max": 0
},
"shadows": {
"enabled": false,
@ -25,23 +25,9 @@
},
"ext": {
"opengl": {
"validation": {
"enabled": true
},
"framebuffer": {
"size": 1,
"msaa": 1
},
"experimental": {
"rebuild on tick begin": false,
"wait on render end": false,
"individual pipelines": true,
"multithreaded command recording": true,
"multithreaded command rendering": false,
"deferred mode": "",
"deferred reconstruct position": true,
"deferred alias output to swapchain": true,
"hdr": false,
"validation": { "enabled": false },
"framebuffer": { "size": 1, "msaa": 1 },
"pipelines": {
"culling": true
},
"formats": {
@ -134,14 +120,16 @@
"window" : {
"terminal" : {
"ncurses" : false,
"visible" : true
"visible" : false
},
"keyboard" : {
"repeat" : false
},
"cursor" : {
"visible" : true,
"center" : false
"center" : false,
"sensitivity": [ 1.25, 1.25 ],
"smoothing": [ 10, 10 ]
},
"mode" : "windowed",
"icon" : "./data/textures/icon.png",

View File

@ -120,32 +120,22 @@ void client::tick() {
if ( client::window.hasFocus() ) {
// fullscreener
TIMER(1, (uf::inputs::kbm::states::LAlt || uf::inputs::kbm::states::RAlt) && uf::inputs::kbm::states::Enter && ) {
UF_MSG_DEBUG("mpoop fullscreen");
client::window.toggleFullscreen( false );
uf::renderer::states::resized = true;
client::window.toggleFullscreen( false );
}
// mouse move
if ( client::config["window"]["mouse"]["center"].as<bool>() ) {
auto previous = client::window.getMousePosition();
client::window.setMousePosition(client::window.getSize()/2);
auto current = client::window.getMousePosition();
auto size = client::window.getSize();
auto current = client::window.getMousePosition();
auto center = client::window.getSize() / 2.0f;
client::window.setMousePosition(client::window.getSize() / 2.0f);
uf::hooks.call("window:Mouse.Moved", pod::payloads::windowMouseMoved{
{
{
"window:Mouse.Moved",
"client",
},
{
pod::Vector2ui{ size.x, size.y },
},
{ "window:Mouse.Moved", "client", },
{ pod::Vector2ui{ size.x, size.y }, },
},
{
current,
previous - current,
0
}
{ center, current - center, 0 }
});
}
}

View File

@ -6,8 +6,10 @@
#include <uf/utils/window/payloads.h>
#include <uf/utils/memory/pool.h>
#include <filesystem>
#include <uf/spec/renderer/universal.h>
#include <filesystem>
#include <signal.h>
namespace {
@ -55,7 +57,6 @@ int main(int argc, char** argv){
client::initialize();
ext::initialize();
// For Multithreaded initialization
while ( !client::ready || !ext::ready ) {
static uf::Timer<long long> timer(false);
@ -67,37 +68,32 @@ int main(int argc, char** argv){
next *= 2;
}
}
while ( client::ready && ext::ready ) {
#if UF_EXCEPTIONS
try {
#endif
/*
static bool first = false; if ( !first ) { first = true;
ext::json::Value json;
uf::hooks.call("window:Resized", pod::payloads::windowResized{
{
"window:Resized",
"os",
},
{ uf::vector::decode( client::config["window"]["size"], pod::Vector2ui{} ) },
if ( uf::renderer::settings::experimental::dedicatedThread /*&& !uf::renderer::states::rebuild*/ ) {
auto& thread = uf::thread::get("Aux");
uf::thread::queue(thread, [&]{
ext::render();
client::render();
});
client::tick();
ext::tick();
uf::thread::wait( thread );
} else {
// UF_TIMER_MULTITRACE_START("Frame Start");
client::tick();
ext::tick();
// UF_TIMER_MULTITRACE("Ticked");
ext::render();
client::render();
// UF_TIMER_MULTITRACE("Rendered");
// UF_TIMER_MULTITRACE_END("Frame End");
}
*/
#if UF_ENV_DREAMCAST
// UF_TIMER_MULTITRACE_START("Starting");
ext::tick();
client::tick();
// UF_TIMER_MULTITRACE("render");
ext::render();
client::render();
// UF_TIMER_MULTITRACE("tick");
// UF_TIMER_MULTITRACE_END("Finished");
#else
client::tick();
client::render();
ext::tick();
ext::render();
#endif
#if UF_EXCEPTIONS
} catch ( std::runtime_error& e ) {
UF_MSG_ERROR("RUNTIME ERROR: " << e.what());

View File

@ -1,8 +1,10 @@
#!/bin/bash
cd bin
PREFIX=$(cat ./exe/default.config)
cp ./exe/lib/win64/*.dll .
cp ./exe/lib/win64/$PREFIX/*.dll .
gdb ./exe/program.$PREFIX.exe
ARCH=$(cat ./exe/default/arch)
CC=$(cat ./exe/default/cc)
RENDERER=$(cat ./exe/default/renderer)
cp ./exe/lib/$ARCH/*.dll .
cp ./exe/lib/$ARCH/$CC/$RENDERER/*.dll .
gdb ./exe/program.$ARCH.$CC.$RENDERER.exe
rm *.dll

View File

@ -52,7 +52,7 @@ namespace uf {
typedef uf::stl::vector<pod::Behavior> container_t;
// typedef uf::stl::vector<pod::Behavior::Header> container_t;
container_t m_behaviors;
struct {
struct Graph {
typedef pod::Behavior::function_t value_t;
// typedef uint_fast8_t value_t;
uf::stl::vector<value_t> initialize;
@ -70,6 +70,9 @@ namespace uf {
container_t& getBehaviors();
const container_t& getBehaviors() const;
Graph& getGraph();
const Graph& getGraph() const;
bool hasBehavior( const pod::Behavior& );
void addBehavior( const pod::Behavior& );
void removeBehavior( const pod::Behavior& );

View File

@ -17,6 +17,8 @@ namespace uf {
// we could keep a cache of controllers for each rendermode, but we have to invalidate the cache every time the graph regenerates
uf::stl::unordered_map<uf::stl::string, uf::Entity*> cache;
#endif
pod::Thread::Tasks tasks;
);
}
}

View File

@ -52,7 +52,7 @@ namespace ext {
template<typename T> T& encode( const ext::json::Value& json, T& output, const ext::json::EncodingSettings& settings = {} );
template<typename T> ext::json::Value& decode( ext::json::Value& json, const T& input, const DecodingSettings& settings = {} );
inline uf::stl::string UF_API encode( const ext::json::Value& json, const ext::json::EncodingSettings& settings = {} ) {
inline uf::stl::string encode( const ext::json::Value& json, const ext::json::EncodingSettings& settings = {} ) {
uf::stl::string output;
encode( json, output, settings );
return output;

View File

@ -26,23 +26,31 @@ namespace ext {
extern UF_API ext::opengl::enums::Filter::type_t swapchainUpscaleFilter;
namespace experimental {
extern UF_API bool dedicatedThread;
extern UF_API bool rebuildOnTickBegin;
extern UF_API bool batchQueueSubmissions;
}
namespace invariant {
extern UF_API bool waitOnRenderEnd;
extern UF_API bool individualPipelines;
extern UF_API bool multithreadedCommandRecording;
extern UF_API bool multithreadedCommandRendering;
extern UF_API bool multithreadedRecording;
extern UF_API uf::stl::string deferredMode;
extern UF_API bool deferredReconstructPosition;
extern UF_API bool deferredAliasOutputToSwapchain;
extern UF_API bool deferredSampling;
extern UF_API bool multiview;
}
namespace pipelines {
extern UF_API bool vsync;
extern UF_API bool hdr;
extern UF_API bool vxgi;
extern UF_API bool deferredSampling;
extern UF_API bool culling;
extern UF_API bool bloom;
}
namespace formats {
extern UF_API GLhandle(VkColorSpaceKHR) colorSpace;
extern UF_API ext::opengl::enums::Format::type_t color;
@ -61,9 +69,9 @@ namespace ext {
extern UF_API std::mutex mutex;
extern UF_API std::mutex immediateModeMutex;
extern UF_API RenderMode* currentRenderMode;
// extern UF_API RenderMode* currentRenderMode;
extern UF_API uf::stl::vector<RenderMode*> renderModes;
extern UF_API uf::stl::vector<uf::Scene*> scenes;
extern UF_API uf::ThreadUnique<RenderMode*> currentRenderMode;
bool UF_API hasRenderMode( const uf::stl::string&, bool = true );
RenderMode& UF_API addRenderMode( RenderMode*, const uf::stl::string& = "" );
@ -71,6 +79,10 @@ namespace ext {
uf::stl::vector<RenderMode*> UF_API getRenderModes( const uf::stl::string&, bool = true );
uf::stl::vector<RenderMode*> UF_API getRenderModes( const uf::stl::vector<uf::stl::string>&, bool = true );
void UF_API removeRenderMode( RenderMode*, bool = true );
RenderMode* UF_API getCurrentRenderMode();
RenderMode* UF_API getCurrentRenderMode( std::thread::id );
void UF_API setCurrentRenderMode( RenderMode* renderMode );
void UF_API setCurrentRenderMode( RenderMode* renderMode, std::thread::id );
void UF_API initialize( /*uint8_t = 0*/ );
void UF_API tick();

View File

@ -1,27 +0,0 @@
#pragma once
#include <uf/ext/opengl/rendermode.h>
#include <uf/ext/opengl/graphic.h>
namespace ext {
namespace opengl {
struct UF_API ComputeRenderMode : public RenderMode {
ext::opengl::Graphic blitter, compute;
pod::Vector2ui dispatchSize = { 32, 32 };
// RAII
virtual const uf::stl::string getType() const;
virtual const size_t blitters() const;
virtual ext::opengl::Graphic* getBlitter(size_t = 0);
virtual uf::stl::vector<ext::opengl::Graphic*> getBlitters();
virtual void createCommandBuffers();
virtual void initialize( Device& device );
virtual void tick();
virtual void render();
virtual void destroy();
virtual void bindPipelines();
virtual void pipelineBarrier( GLhandle(VkCommandBuffer), uint8_t = -1 );
};
}
}

View File

@ -17,6 +17,7 @@ namespace ext {
virtual void createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& graphics );
virtual void initialize( Device& device );
virtual void tick();
virtual void render();
virtual void destroy();
};
}

View File

@ -11,7 +11,7 @@ namespace ext {
namespace vulkan {
struct Graphic;
struct UF_API Pipeline {
struct UF_API Pipeline : public Buffers {
bool aliased = false;
Device* device = NULL;

View File

@ -8,7 +8,7 @@ namespace ext {
namespace vulkan {
struct Graphic;
struct UF_API RenderMode {
struct UF_API RenderMode : public Buffers {
bool execute = false;
bool executed = false;
bool rebuild = false;
@ -57,6 +57,15 @@ namespace ext {
uf::stl::unordered_map<int32_t, callback_t> commandBufferCallbacks;
void bindCallback( int32_t, const callback_t& );
uf::Image screenshot(size_t = 0, size_t = 0);
commands_container_t& getCommands();
commands_container_t& getCommands( std::thread::id );
void lockMutex();
void lockMutex( std::thread::id );
void unlockMutex();
void unlockMutex( std::thread::id );
virtual ~RenderMode();
// RAII
@ -69,10 +78,6 @@ namespace ext {
virtual ext::vulkan::Graphic* getBlitter(size_t = 0);
virtual uf::stl::vector<ext::vulkan::Graphic*> getBlitters();
virtual uf::Image screenshot(size_t = 0, size_t = 0);
virtual commands_container_t& getCommands();
virtual commands_container_t& getCommands( std::thread::id );
virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 );
@ -86,6 +91,8 @@ namespace ext {
virtual void destroy();
virtual void synchronize( uint64_t = UINT64_MAX );
virtual void pipelineBarrier( VkCommandBuffer, uint8_t = -1 );
virtual VkSubmitInfo queue();
};
}
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <uf/ext/vulkan/rendermode.h>
#include <uf/ext/vulkan/graphic.h>
namespace ext {
namespace vulkan {
struct UF_API ComputeRenderMode : public ext::vulkan::RenderMode {
ext::vulkan::Graphic blitter, compute;
//
virtual const uf::stl::string getType() const;
virtual const size_t blitters() const;
virtual ext::vulkan::Graphic* getBlitter(size_t = 0);
virtual uf::stl::vector<ext::vulkan::Graphic*> getBlitters();
virtual void createCommandBuffers();
virtual void initialize( Device& device );
virtual void tick();
virtual void render();
virtual void destroy();
virtual void bindPipelines();
virtual void pipelineBarrier( VkCommandBuffer, uint8_t = -1 );
};
}
}

View File

@ -18,6 +18,8 @@ namespace ext {
virtual void createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics );
virtual void initialize( Device& device );
virtual void tick();
virtual VkSubmitInfo queue();
virtual void render();
virtual void destroy();
};
}

View File

@ -41,6 +41,7 @@ namespace ext {
extern UF_API uint8_t msaa;
extern UF_API bool validation;
extern UF_API size_t viewCount;
extern UF_API size_t gpuID;
constexpr size_t maxViews = 6;
extern UF_API uf::stl::vector<uf::stl::string> validationFilters;
@ -51,19 +52,27 @@ namespace ext {
extern UF_API VkFilter swapchainUpscaleFilter;
namespace experimental {
extern UF_API bool dedicatedThread;
extern UF_API bool rebuildOnTickBegin;
extern UF_API bool batchQueueSubmissions;
}
namespace invariant {
extern UF_API bool waitOnRenderEnd;
extern UF_API bool individualPipelines;
extern UF_API bool multithreadedCommandRecording;
extern UF_API bool multithreadedCommandRendering;
extern UF_API bool multithreadedRecording;
extern UF_API uf::stl::string deferredMode;
extern UF_API bool deferredReconstructPosition;
extern UF_API bool deferredAliasOutputToSwapchain;
extern UF_API bool deferredSampling;
extern UF_API bool multiview;
}
namespace pipelines {
extern UF_API bool vsync;
extern UF_API bool hdr;
extern UF_API bool vxgi;
extern UF_API bool deferredSampling;
extern UF_API bool culling;
extern UF_API bool bloom;
}
@ -87,10 +96,10 @@ namespace ext {
extern UF_API Swapchain swapchain;
extern UF_API std::mutex mutex;
extern UF_API RenderMode* currentRenderMode;
// extern UF_API RenderMode* currentRenderMode;
extern UF_API uf::stl::vector<RenderMode*> renderModes;
extern UF_API uf::stl::unordered_map<uf::stl::string, RenderMode*> renderModesMap;
extern UF_API uf::stl::vector<uf::Scene*> scenes;
extern UF_API uf::ThreadUnique<RenderMode*> currentRenderMode;
bool UF_API hasRenderMode( const uf::stl::string&, bool = true );
RenderMode& UF_API addRenderMode( RenderMode*, const uf::stl::string& = "" );
@ -98,6 +107,10 @@ namespace ext {
uf::stl::vector<RenderMode*> UF_API getRenderModes( const uf::stl::string&, bool = true );
uf::stl::vector<RenderMode*> UF_API getRenderModes( const uf::stl::vector<uf::stl::string>&, bool = true );
void UF_API removeRenderMode( RenderMode*, bool = true );
RenderMode* UF_API getCurrentRenderMode();
RenderMode* UF_API getCurrentRenderMode( std::thread::id );
void UF_API setCurrentRenderMode( RenderMode* renderMode );
void UF_API setCurrentRenderMode( RenderMode* renderMode, std::thread::id );
void UF_API initialize( /*uint8_t = 0*/ );
void UF_API tick();

View File

@ -79,13 +79,13 @@
#define UF_TIMER_TRACE_INIT() uf::Timer<long long> TIMER_TRACE;
#define UF_TIMER_TRACE(X) {\
auto elapsed = TIMER_TRACE.elapsed().asMilliseconds();\
if ( elapsed > 0 ) UF_MSG_DEBUG(TIMER_TRACE.elapsed().asMilliseconds() << "ms\t" << X);\
auto elapsed = TIMER_TRACE.elapsed().asMicroseconds();\
if ( elapsed > 0 ) UF_MSG_DEBUG(TIMER_TRACE.elapsed().asMicroseconds() << "us\t" << X);\
}
#define UF_TIMER_TRACE_RESET(X) {\
auto elapsed = TIMER_TRACE.elapsed().asMilliseconds();\
if ( elapsed > 0 ) UF_MSG_DEBUG(TIMER_TRACE.elapsed().asMilliseconds() << "ms\t" << X);\
auto elapsed = TIMER_TRACE.elapsed().asMicroseconds();\
if ( elapsed > 0 ) UF_MSG_DEBUG(TIMER_TRACE.elapsed().asMicroseconds() << "us\t" << X);\
TIMER_TRACE.reset();\
}
@ -95,8 +95,8 @@
UF_MSG_DEBUG(X);\
#define UF_TIMER_MULTITRACE(X) {\
TIMER_TRACE_CUR = TIMER_TRACE.elapsed().asMilliseconds();\
UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " ms\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " ms\t" << X);\
TIMER_TRACE_CUR = TIMER_TRACE.elapsed().asMicroseconds();\
UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " ns\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " ns\t" << X);\
TIMER_TRACE_PREV = TIMER_TRACE_CUR;\
}

View File

@ -4,7 +4,6 @@
#include <uf/ext/opengl/graphic.h>
#include <uf/ext/opengl/rendermodes/rendertarget.h>
#include <uf/ext/opengl/rendermodes/deferred.h>
#include <uf/ext/opengl/rendermodes/compute.h>
#include <uf/ext/opengl/rendertarget.h>
namespace spec {

View File

@ -4,7 +4,6 @@
#include <uf/ext/vulkan/graphic.h>
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
#include <uf/ext/vulkan/rendermodes/deferred.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/rendertarget.h>
namespace spec {

View File

@ -11,6 +11,7 @@
#include <stdint.h>
#include <uf/ext/json/json.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/math/angle.h>
namespace pod {

View File

@ -12,7 +12,7 @@ namespace uf {
// bool match( const uf::stl::string& str, const uf::stl::string& r );
bool UF_API isRegex( const uf::stl::string& str );
uf::stl::vector<uf::stl::string> UF_API match( const uf::stl::string& str, const uf::stl::string& r );
inline uf::stl::vector<uf::stl::string> UF_API matches( const uf::stl::string& str, const uf::stl::string& r ) { return uf::string::match( str, r ); }
inline uf::stl::vector<uf::stl::string> matches( const uf::stl::string& str, const uf::stl::string& r ) { return uf::string::match( str, r ); }
bool UF_API matched( const uf::stl::string& str, const uf::stl::string& r );

View File

@ -8,13 +8,23 @@ namespace uf {
class UF_API ThreadUnique {
public:
typedef T type_t;
typedef std::mutex* mutex_type_t;
typedef std::thread::id id_t;
typedef uf::stl::unordered_map<id_t, type_t> container_t;
typedef uf::stl::unordered_map<id_t, mutex_type_t> mutex_container_t;
protected:
container_t m_container;
mutex_container_t m_mutex_container;
public:
~ThreadUnique();
bool has( id_t id = std::this_thread::get_id() ) const;
T& get( id_t id = std::this_thread::get_id() );
void lock( id_t id = std::this_thread::get_id() );
void unlock( id_t id = std::this_thread::get_id() );
std::lock_guard<std::mutex> guard( id_t id = std::this_thread::get_id() );
container_t& container();
};
}

View File

@ -1,3 +1,12 @@
template<typename T>
uf::ThreadUnique<T>::~ThreadUnique() {
for ( auto& pair : m_mutex_container ) {
if ( !pair.second ) continue;
delete pair.second;
pair.second = NULL;
}
}
template<typename T>
bool uf::ThreadUnique<T>::has( id_t id ) const {
return m_container.count(id) > 0;
@ -7,6 +16,21 @@ T& uf::ThreadUnique<T>::get( id_t id ) {
return m_container[id];
}
template<typename T>
void uf::ThreadUnique<T>::lock( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
m_mutex_container[id]->lock();
}
template<typename T>
void uf::ThreadUnique<T>::unlock( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
m_mutex_container[id]->unlock();
}
template<typename T>
std::lock_guard<std::mutex> uf::ThreadUnique<T>::guard( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
return std::lock_guard<std::mutex>(*m_mutex_container[id]);
}
template<typename T>
typename uf::ThreadUnique<T>::container_t& uf::ThreadUnique<T>::container() {
return m_container;
}

View File

@ -31,12 +31,25 @@ namespace pod {
std::condition_variable condition;
std::thread thread;
pod::Thread::queue_t temps;
pod::Thread::container_t consts;
pod::Thread::queue_t queue;
pod::Thread::container_t container;
uf::Timer<long long> timer;
uint affinity = 0;
struct UF_API Tasks {
uf::stl::string name = "Aux";
bool waits = true;
pod::Thread::queue_t container;
inline void add( const pod::Thread::function_t& fun ) { container.emplace(fun); }
inline void emplace( const pod::Thread::function_t& fun ) { container.emplace(fun); }
inline void queue( const pod::Thread::function_t& fun ) { container.emplace(fun); }
inline void clear() { container = {}; }
};
};
}
namespace uf {
@ -46,29 +59,14 @@ namespace uf {
extern UF_API std::thread::id mainThreadId;
extern UF_API bool async;
/* Acts on thread */
void UF_API start( pod::Thread& );
void UF_API quit( pod::Thread& );
void UF_API tick( pod::Thread& );
// void UF_API tick( pod::Thread&, const std::function<void()>& = NULL );
/* Easy to use async helper functions */
pod::Thread& UF_API fetchWorker( const uf::stl::string& name = "Aux" );
void UF_API batchWorker( const pod::Thread::function_t&, const uf::stl::string& name = "Aux" );
void UF_API batchWorkers( const uf::stl::vector<pod::Thread::function_t>&, bool = true, const uf::stl::string& name = "Aux" );
void UF_API batchWorkers_Async( const uf::stl::vector<pod::Thread::function_t>&, bool = true, const uf::stl::string& name = "Aux" );
void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false );
void UF_API process( pod::Thread& );
pod::Thread::Tasks UF_API schedule( const uf::stl::string& name = "Aux", bool waits = true );
void UF_API execute( pod::Thread::Tasks& tasks );
void UF_API wait( pod::Thread& );
const uf::stl::string& UF_API name( const pod::Thread& );
uint UF_API uid( const pod::Thread& );
bool UF_API running( const pod::Thread& );
/* Acts on global threads */
typedef uf::stl::vector<pod::Thread*> container_t;
extern UF_API uf::thread::container_t threads;
void UF_API terminate();
@ -80,57 +78,29 @@ namespace uf {
pod::Thread& UF_API get( const uf::stl::string& );
bool UF_API isMain();
/* Acts on thread */
void UF_API start( pod::Thread& );
void UF_API quit( pod::Thread& );
void UF_API tick( pod::Thread& );
// schedules to worker thread
void UF_API queue( const pod::Thread::function_t& fun );
void UF_API queue( const pod::Thread::container_t& funs );
// schedules to target thread
void UF_API queue( pod::Thread& thread, const pod::Thread::function_t& fun );
void UF_API add( pod::Thread& thread, const pod::Thread::function_t& fun );
// schedules to named thread
inline void queue( const uf::stl::string& name, const pod::Thread::function_t& fun ) { return uf::thread::queue( uf::thread::get(name), fun ); }
inline void add( const uf::stl::string& name, const pod::Thread::function_t& fun ) { return uf::thread::add( uf::thread::get(name), fun ); }
void UF_API process( pod::Thread& );
void UF_API wait( pod::Thread& );
const uf::stl::string& UF_API name( const pod::Thread& );
uint UF_API uid( const pod::Thread& );
bool UF_API running( const pod::Thread& );
}
}
/*
namespace uf {
class UF_API Thread {
public:
typedef std::function<int()> function_t;
typedef std::queue<uf::Thread::function_t> queue_t;
typedef uf::stl::vector<uf::Thread::function_t> container_t;
enum {
TEMP = 0,
CONSTANT = 1,
};
protected:
uint m_uid;
uint m_mode;
bool m_running;
bool m_shouldLock;
bool m_terminateOnEmpty;
std::mutex m_mutex;
uf::stl::string m_name;
std::thread m_thread;
uf::Thread::queue_t m_temps;
uf::Thread::container_t m_consts;
public:
static uint fps;
static uint thread_count;
Thread( const uf::stl::string& = "", bool = true, uint = 0 );
virtual ~Thread();
void start();
virtual void tick(const std::function<void()>& = NULL);
void add( const uf::Thread::function_t&, uint = 0 );
void process();
void quit();
uf::stl::string toString() const;
const uf::stl::string& getName() const;
uint getUid() const;
const bool& isRunning() const;
};
namespace thread {
typedef uf::stl::unordered_map<uf::stl::string, uf::Thread*> container_t;
extern UF_API uf::thread::container_t threads;
void UF_API add( uf::Thread* );
uf::Thread& UF_API get( const uf::stl::string& );
bool UF_API add( const uf::stl::string&, const uf::Thread::function_t&, uint = 0 );
bool UF_API quit( const uf::stl::string& );
};
}
*/
}

View File

@ -50,7 +50,7 @@ uf::Asset uf::Asset::masterAssetLoader;
bool uf::Asset::assertionLoad = true;
void uf::Asset::processQueue() {
uf::thread::batchWorker( [&](){
uf::thread::queue([&]{
mutex.lock();
auto jobs = std::move(this->getComponent<std::queue<Job>>());
while ( !jobs.empty() ) {
@ -69,102 +69,6 @@ void uf::Asset::processQueue() {
}
mutex.unlock();
});
#if 0
auto& jobs = this->getComponent<std::queue<Job>>();
mutex.lock();
uf::stl::vector<std::function<void()>> tasks;
while ( !jobs.empty() ) {
auto job = jobs.front();
jobs.pop();
if ( job.uri == "" || job.callback == "" ) continue;
tasks.emplace_back([=](){
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.mime) : this->load(job.uri, job.hash, job.mime);
if ( filename == "" ) return;
ext::json::Value payload;
payload["filename"] = filename;
payload["hash"] = job.hash;
payload["mime"] = job.mime;
uf::hooks.call(job.callback, payload);
});
}
uf::thread::batchWorkers( tasks, false );
mutex.unlock();
#elif 0
auto& jobs = this->getComponent<std::queue<Job>>();
mutex.lock();
while ( !jobs.empty() ) {
auto job = jobs.front();
jobs.pop();
uf::stl::string callback = job.callback;
uf::stl::string type = job.type;
uf::stl::string uri = job.uri;
uf::stl::string hash = job.hash;
uf::stl::string mime = job.mime;
if ( uri == "" || callback == "" ) {
continue;
}
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, mime) : this->load(uri, hash, mime);
if ( callback != "" && filename != "" ) {
ext::json::Value payload;
payload["filename"] = filename;
payload["hash"] = hash;
payload["mime"] = mime;
uf::hooks.call(callback, payload);
}
}
mutex.unlock();
#elif 0
uf::thread::batchWorker( [&](){
mutex.lock();
auto jobs = std::move(this->getComponent<std::queue<Job>>());
while ( !jobs.empty() ) {
auto job = jobs.front();
jobs.pop();
uf::stl::string callback = job.callback;
uf::stl::string type = job.type;
uf::stl::string uri = job.uri;
uf::stl::string hash = job.hash;
uf::stl::string mime = job.mime;
if ( uri == "" || callback == "" ) {
continue;
}
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, mime) : this->load(uri, hash, mime);
if ( callback != "" && filename != "" ) {
ext::json::Value payload;
payload["filename"] = filename;
payload["hash"] = hash;
payload["mime"] = mime;
uf::hooks.call(callback, payload);
}
}
mutex.unlock();
});
#elif 0
uf::thread::batchWorker( [&](){
mutex.lock();
auto jobs = std::move(this->getComponent<std::queue<Job>>());
uf::stl::vector<std::function<void()>> tasks;
while ( !jobs.empty() ) {
auto job = jobs.front();
jobs.pop();
if ( job.uri == "" || job.callback == "" ) continue;
tasks.emplace_back([=](){
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.mime) : this->load(job.uri, job.hash, job.mime);
if ( filename == "" ) return;
ext::json::Value payload;
payload["filename"] = filename;
payload["hash"] = job.hash;
payload["mime"] = job.mime;
uf::hooks.call(job.callback, payload);
});
}
uf::thread::batchWorkers( tasks, false );
mutex.unlock();
});
#endif
}
void uf::Asset::cache( const uf::stl::string& callback, const uf::Asset::Payload& payload ) {
mutex.lock();

View File

@ -3,6 +3,7 @@
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/thread/thread.h>
#define UF_GRAPH_PRINT_TRACE 0
#define UF_BEHAVIORS_REMOVE_STL_FIND 1
uf::Behaviors::container_t& uf::Behaviors::getBehaviors() { return m_behaviors; }
@ -29,6 +30,8 @@ void uf::Behaviors::removeBehavior( const pod::Behavior& behavior ) {
m_behaviors.erase(it);
generateGraph();
}
uf::Behaviors::Graph& uf::Behaviors::getGraph() { return m_graph; }
const uf::Behaviors::Graph& uf::Behaviors::getGraph() const { return m_graph; }
void uf::Behaviors::generateGraph() {
m_graph.initialize.clear();
m_graph.tick.clear();
@ -82,31 +85,33 @@ void uf::Behaviors::initialize() {
void uf::Behaviors::tick() {
uf::Object& self = *((uf::Object*) this);
if ( !self.isValid() ) return;
// if ( !m_graph.tickMT.empty() ) uf::thread::queue(m_graph.tickMT);
if ( m_graph.tick.empty() ) return;
// if ( !m_graph.tickMT.empty() ) uf::thread::batchWorkers(m_graph.tickMT, false);
/*
UF_TIMER_MULTITRACE_START("Starting " << self.getName() << ": " << self.getUid());
#if UF_GRAPH_PRINT_TRACE
UF_TIMER_MULTITRACE_START("Starting tick " << self.getName() << ": " << self.getUid());
for ( auto& fun : m_graph.tick ) {
fun(self);
UF_TIMER_MULTITRACE("");
}
UF_TIMER_MULTITRACE_END("Finished " << self.getName() << ": " << self.getUid())
*/
UF_TIMER_MULTITRACE_END("Finished tick " << self.getName() << ": " << self.getUid())
#else
UF_BEHAVIOR_POLYFILL(tick)
#endif
}
void uf::Behaviors::render() {
uf::Object& self = *((uf::Object*) this);
if ( !self.isValid() ) return;
if ( m_graph.render.empty() ) return;
/*
UF_TIMER_MULTITRACE_START("Starting " << self.getName() << ": " << self.getUid());
#if UF_GRAPH_PRINT_TRACE
UF_TIMER_MULTITRACE_START("Starting render " << self.getName() << ": " << self.getUid());
for ( auto& fun : m_graph.render ) {
fun(self);
UF_TIMER_MULTITRACE("");
}
UF_TIMER_MULTITRACE_END("Finished " << self.getName() << ": " << self.getUid())
*/
UF_TIMER_MULTITRACE_END("Finished render " << self.getName() << ": " << self.getUid())
#else
UF_BEHAVIOR_POLYFILL(render)
#endif
}
void uf::Behaviors::destroy() {
uf::Object& self = *((uf::Object*) this);

View File

@ -3,7 +3,7 @@
#include <uf/engine/instantiator/instantiator.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(uf::Entity)
UF_BEHAVIOR_TRAITS_CPP(uf::EntityBehavior, ticks = true, renders = false, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(uf::EntityBehavior, ticks = false, renders = false, multithread = false)
#define this ((uf::Entity*) &self)
void uf::EntityBehavior::initialize( uf::Object& self ) {
if ( !this->isValid() ) this->setUid();

View File

@ -306,9 +306,13 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
graph.name = filename; //serializer["name"].as<uf::stl::string>();
graph.metadata = metadata; // serializer["metadata"];
pod::Thread::container_t jobs;
#if UF_GRAPH_LOAD_MULTITHREAD
auto tasks = uf::thread::schedule("Async");
#else
auto tasks = uf::thread::schedule("Main");
#endif
jobs.emplace_back([&]{
tasks.queue([&]{
// load images
UF_DEBUG_TIMER_MULTITRACE("Reading instances...");
graph.instances.reserve( serializer["instances"].size() );
@ -322,7 +326,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load images
UF_DEBUG_TIMER_MULTITRACE("Reading primitives...");
graph.primitives.reserve( serializer["primitives"].size() );
@ -335,7 +339,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load images
UF_DEBUG_TIMER_MULTITRACE("Reading drawCommands...");
graph.drawCommands.reserve( serializer["drawCommands"].size() );
@ -348,7 +352,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load mesh information
UF_DEBUG_TIMER_MULTITRACE("Reading meshes...");
graph.meshes.reserve( serializer["meshes"].size() );
@ -361,7 +365,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load images
UF_DEBUG_TIMER_MULTITRACE("Reading images...");
graph.images.reserve( serializer["images"].size() );
@ -388,7 +392,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
}
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load texture information
UF_DEBUG_TIMER_MULTITRACE("Reading texture information...");
graph.textures.reserve( serializer["textures"].size() );
@ -401,7 +405,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load sampler information
UF_DEBUG_TIMER_MULTITRACE("Reading sampler information...");
graph.samplers.reserve( serializer["samplers"].size() );
@ -414,7 +418,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load material information
UF_DEBUG_TIMER_MULTITRACE("Reading material information...");
graph.materials.reserve( serializer["materials"].size() );
@ -427,7 +431,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load light information
UF_DEBUG_TIMER_MULTITRACE("Reading lighting information...");
graph.lights.reserve( serializer["lights"].size() );
@ -439,7 +443,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load animation information
UF_DEBUG_TIMER_MULTITRACE("Reading animation information...");
/*graph.storage*/uf::graph::storage.animations.map.reserve( serializer["animations"].size() );
@ -458,7 +462,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load skin information
UF_DEBUG_TIMER_MULTITRACE("Reading skinning information...");
graph.skins.reserve( serializer["skins"].size() );
@ -471,7 +475,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
jobs.emplace_back([&]{
tasks.queue([&]{
// load node information
UF_DEBUG_TIMER_MULTITRACE("Reading nodes...");
graph.nodes.reserve( serializer["nodes"].size() );
@ -483,11 +487,8 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize
DC_STATS();
#endif
});
#if UF_GRAPH_LOAD_MULTITHREAD
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
#else
for ( auto& job : jobs ) job();
#endif
uf::thread::execute( tasks );
// re-reference all transform parents
for ( auto& node : graph.nodes ) {

View File

@ -261,8 +261,12 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
*/
#endif
pod::Thread::container_t jobs;
jobs.emplace_back([&]{
#if UF_GRAPH_LOAD_MULTITHREAD
auto tasks = uf::thread::schedule("Async");
#else
auto tasks = uf::thread::schedule("Main");
#endif
tasks.queue([&]{
ext::json::reserve( serializer["instances"], graph.instances.size() );
for ( size_t i = 0; i < graph.instances.size(); ++i ) {
auto& name = graph.instances[i];
@ -272,7 +276,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["instances"].emplace_back( json );
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
ext::json::reserve( serializer["primitives"], graph.primitives.size() );
for ( size_t i = 0; i < graph.primitives.size(); ++i ) {
auto& name = graph.primitives[i];
@ -285,7 +289,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
ext::json::reserve( serializer["drawCommands"], graph.drawCommands.size() );
for ( size_t i = 0; i < graph.drawCommands.size(); ++i ) {
auto& name = graph.drawCommands[i];
@ -298,7 +302,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store mesh information
ext::json::reserve( serializer["meshes"], graph.meshes.size() );
if ( !settings.combined ) {
@ -330,7 +334,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
});
#if 0
jobs.emplace_back([&]{
tasks.queue([&]{
if ( uf::graphs::storage.atlases[graph.atlas].generated() ) {
auto atlasName = filename + "/" + "atlas";
auto& atlas = /*graph.storage*/uf::graph::storage.atlases[atlasName];
@ -344,7 +348,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
});
#endif
jobs.emplace_back([&]{
tasks.queue([&]{
ext::json::reserve( serializer["images"], graph.images.size() );
if ( !settings.combined ) {
for ( size_t i = 0; i < graph.images.size(); ++i ) {
@ -367,7 +371,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store texture information
ext::json::reserve( serializer["textures"], graph.textures.size() );
for ( auto& name : graph.textures ) {
@ -377,7 +381,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["textures"].emplace_back(json);
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store sampler information
ext::json::reserve( serializer["samplers"], graph.samplers.size() );
for ( auto& name : graph.samplers ) {
@ -387,7 +391,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["samplers"].emplace_back(json);
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store material information
ext::json::reserve( serializer["materials"], graph.materials.size() );
for ( auto& name : graph.materials ) {
@ -397,7 +401,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["materials"].emplace_back(json);
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store light information
ext::json::reserve( serializer["lights"], graph.lights.size() );
for ( auto pair : graph.lights ) {
@ -408,7 +412,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["lights"].emplace_back(json);
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store animation information
ext::json::reserve( serializer["animations"], graph.animations.size() );
if ( !settings.combined ) {
@ -426,7 +430,7 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
}
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store skin information
ext::json::reserve( serializer["skins"], graph.skins.size() );
for ( auto& name : graph.skins ) {
@ -434,17 +438,14 @@ uf::stl::string uf::graph::save( const pod::Graph& graph, const uf::stl::string&
serializer["skins"].emplace_back( encode(skin, settings, graph) );
}
});
jobs.emplace_back([&]{
tasks.queue([&]{
// store node information
ext::json::reserve( serializer["nodes"], graph.nodes.size() );
for ( auto& node : graph.nodes ) serializer["nodes"].emplace_back( encode(node, settings, graph) );
serializer["root"] = encode(graph.root, settings, graph);
});
#if UF_GRAPH_LOAD_MULTITHREAD
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
#else
for ( auto& job : jobs ) job();
#endif
uf::thread::execute( tasks );
if ( !settings.combined ) target = directory + "/graph.json";
serializer.writeToFile( target );

View File

@ -87,18 +87,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
// for ( auto& i : graph.images ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[i] );
// for ( auto pair : uf::graph::storage.texture2Ds.map ) graphic.material.textures.emplace_back().aliasTexture( pair.second );
#if 1
for ( auto& key : uf::graph::storage.texture2Ds.keys ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[key] );
#else
uf::stl::map<size_t, uf::stl::string> texture2DOrderedMap; // texture2DOrderedMap.reserve( uf::graph::storage.texture2Ds.keys.size() );
for ( auto key : uf::graph::storage.texture2Ds.keys ) {
texture2DOrderedMap[uf::graph::storage.texture2Ds.indices[key]] = key;
}
for ( auto pair : texture2DOrderedMap ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[pair.second] );
#endif
// bind scene's voxel texture
if ( uf::renderer::settings::experimental::vxgi ) {
if ( uf::renderer::settings::pipelines::vxgi ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t);
@ -129,7 +121,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/base.frag.spv"); {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
{ uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY(settings) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
fragmentShaderFilename = entity.resolveURI( fragmentShaderFilename, root );
@ -190,7 +182,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
#if UF_USE_VULKAN
// culling pipeline
if ( uf::renderer::settings::experimental::culling ) {
if ( uf::renderer::settings::pipelines::culling ) {
uf::renderer::Buffer* indirect = NULL;
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
UF_ASSERT( indirect );
@ -248,7 +240,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
}
// vxgi pipeline
if ( uf::renderer::settings::experimental::vxgi ) {
if ( uf::renderer::settings::pipelines::vxgi ) {
uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/base.vert.spv");
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("/graph/voxelize.geom.spv");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/voxelize.frag.spv");
@ -359,8 +351,8 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
}
#endif
uf::instantiator::bind( "GraphBehavior", entity );
uf::instantiator::unbind( "RenderBehavior", entity );
// uf::instantiator::bind( "GraphBehavior", entity );
// uf::instantiator::unbind( "RenderBehavior", entity );
}
void uf::graph::process( pod::Graph& graph ) {
@ -742,9 +734,12 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
{
if ( graph.lights.count(node.name) > 0 ) {
auto& l = graph.lights[node.name];
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL
metadata.system.ignoreGraph = true;
#else
metadata.system.ignoreGraph = graph.metadata["debug"]["static"].as<bool>();
#endif
uf::Serializer metadataLight;
metadataLight["radius"][0] = 0.001;
metadataLight["radius"][1] = l.range; // l.range <= 0.001f ? graph.metadata["lights"]["range cap"].as<float>() : l.range;
@ -843,7 +838,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
}
}
if ( (graph.metadata["flags"]["SEPARATE"].as<bool>()) && graph.metadata["flags"]["RENDER"].as<bool>() ) {
uf::instantiator::bind("RenderBehavior", entity);
// uf::instantiator::bind("RenderBehavior", entity);
auto& graphic = entity.getComponent<uf::Graphic>();
graphic.initialize();
@ -948,7 +943,7 @@ void uf::graph::initialize( pod::Graph& graph ) {
initializeShaders( graph, entity->as<uf::Object>() );
uf::instantiator::bind( "GraphBehavior", *entity );
uf::instantiator::unbind( "RenderBehavior", *entity );
// uf::instantiator::unbind( "RenderBehavior", *entity );
if ( entity->getUid() == 0 ) entity->initialize();
//UF_MSG_DEBUG( "Initialized " << uf::string::toString( entity->as<uf::Object>() ) );
*/
@ -1145,10 +1140,32 @@ void uf::graph::tick() {
::newGraphAdded = false;
}
}
void uf::graph::render() {
void uf::graph::render() {
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
#if 0
{
static uf::Entity* lastController = NULL;
if ( lastController == &controller ) return;
lastController = &controller;
uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) );
}
#endif
auto* renderMode = uf::renderer::getCurrentRenderMode();
if ( !renderMode ) return;
#if UF_USE_VULKAN
for ( auto& buffer : renderMode->buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(pod::Camera::Viewports) ) continue;
buffer.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) );
return;
}
#endif
uf::graph::storage.buffers.camera.update( (const void*) &camera.data().viewport, sizeof(pod::Camera::Viewports) );
}
void uf::graph::destroy() {

View File

@ -184,6 +184,10 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
auto& audio = this->getComponent<uf::MappedSoundEmitter>();
audio.update();
}
if ( this->hasComponent<pod::Graph>() ) {
auto& graph = this->getComponent<pod::Graph>();
uf::graph::update( graph );
}
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
#if UF_ENTITY_METADATA_USE_JSON

View File

@ -14,7 +14,7 @@
#include <uf/utils/string/hash.h>
UF_BEHAVIOR_REGISTER_CPP(uf::GraphBehavior)
UF_BEHAVIOR_TRAITS_CPP(uf::GraphBehavior, ticks = true, renders = true, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(uf::GraphBehavior, ticks = false, renders = false, multithread = false)
#define this (&self)
void uf::GraphBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();
@ -72,11 +72,11 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
}
void uf::GraphBehavior::destroy( uf::Object& self ) {}
void uf::GraphBehavior::tick( uf::Object& self ) {
#if 0
if ( this->hasComponent<pod::Graph>() ) {
auto& graph = this->getComponent<pod::Graph>();
uf::graph::update( graph );
}
#if 0
/* Update animations */ if ( this->hasComponent<pod::Graph>() ) {
auto& graph = this->getComponent<pod::Graph>();
// if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) uf::graph::update( graph );

View File

@ -14,7 +14,7 @@
#define UF_UNIFORMS_UPDATE_WITH_JSON 0
UF_BEHAVIOR_REGISTER_CPP(uf::RenderBehavior)
UF_BEHAVIOR_TRAITS_CPP(uf::RenderBehavior, ticks = true, renders = true, multithread = false)
UF_BEHAVIOR_TRAITS_CPP(uf::RenderBehavior, ticks = false, renders = false, multithread = false)
#define this (&self)
void uf::RenderBehavior::initialize( uf::Object& self ) {}
void uf::RenderBehavior::tick( uf::Object& self ) {

View File

@ -17,14 +17,15 @@ namespace {
uf::SceneBehavior::Metadata metadata;
}
#endif
uf::Entity& uf::Scene::getController() {
#if !UF_SCENE_GLOBAL_GRAPH
auto& metadata = this->getComponent<uf::SceneBehavior::Metadata>();
#endif
#if 1
auto currentRenderMode = uf::renderer::getCurrentRenderMode();
uf::Entity* controller = NULL;
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( currentRenderMode ) {
auto& renderMode = *currentRenderMode;
auto& name = renderMode.getName();
if ( metadata.cache.count(name) > 0 ) {
controller = metadata.cache[name];
@ -43,27 +44,6 @@ uf::Entity& uf::Scene::getController() {
}
controller = this->findByName("Player");
return *(metadata.cache[""] = controller ? controller : this);
#else
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( metadata.cached.renderMode == &renderMode && metadata.cached.controller && metadata.cached.controller->isValid() ) {
return *metadata.cached.controller;
}
metadata.cached.controller = NULL;
metadata.cached.renderMode = &renderMode;
auto split = uf::string::split( renderMode.getName(), ":" );
if ( split.front() == "RT" ) {
uint64_t uid = std::stoi( split.back() );
uf::Entity* ent = this->findByUid( uid );
if ( ent ) return *(metadata.cached.controller = ent);
}
}
if ( metadata.cached.controller && metadata.cached.controller->isValid() ) return *metadata.cached.controller;
metadata.cached.controller = this->findByName("Player");
return metadata.cached.controller ? *metadata.cached.controller : *this;
// return this;
#endif
}
const uf::Entity& uf::Scene::getController() const {
uf::Scene& scene = *const_cast<uf::Scene*>(this);
@ -79,6 +59,7 @@ void uf::Scene::invalidateGraph() {
metadata.invalidationQueued = true;
#if 1
metadata.cache.clear();
metadata.tasks.clear();
#else
metadata.cached.renderMode = NULL;
metadata.cached.controller = NULL;
@ -91,12 +72,18 @@ const uf::stl::vector<uf::Entity*>& uf::Scene::getGraph() {
if ( metadata.invalidationQueued ) {
metadata.invalidationQueued = false;
metadata.graph.clear();
metadata.tasks.clear();
}
if ( !metadata.graph.empty() ) return metadata.graph;
this->process([&]( uf::Entity* entity ) {
if ( !entity->hasComponent<uf::ObjectBehavior::Metadata>() ) return;
auto& eMetadata = entity->getComponent<uf::ObjectBehavior::Metadata>();
if ( !eMetadata.system.ignoreGraph ) metadata.graph.emplace_back(entity);
if ( !eMetadata.system.ignoreGraph ) {
metadata.graph.emplace_back(entity);
auto& behaviorGraph = entity->getGraph();
for ( auto& fun : behaviorGraph.tickMT ) metadata.tasks.queue(fun);
}
});
uf::renderer::states::rebuild = true;
return metadata.graph;
@ -114,7 +101,7 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::stl::str
const uf::stl::string filename = _filename != "" ? _filename : ("/" + uf::string::lowercase(name) + "/scene.json");
scene->load(filename);
if ( uf::renderer::settings::experimental::vxgi ) {
if ( uf::renderer::settings::pipelines::vxgi ) {
uf::instantiator::bind( "VoxelizerBehavior", *scene );
}
scene->initialize();
@ -124,7 +111,7 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::Serializ
uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene;
uf::scene::scenes.emplace_back( scene );
if ( data != "" ) scene->load(data);
if ( uf::renderer::settings::experimental::vxgi ) {
if ( uf::renderer::settings::pipelines::vxgi ) {
uf::instantiator::bind( "VoxelizerBehavior", *scene );
}
scene->initialize();
@ -149,8 +136,21 @@ void uf::scene::invalidateGraphs() {
void uf::scene::tick() {
if ( scenes.empty() ) return;
auto graph = uf::scene::getCurrentScene().getGraph(true);
auto& scene = uf::scene::getCurrentScene();
#if !UF_SCENE_GLOBAL_GRAPH
auto& metadata = scene.getComponent<uf::SceneBehavior::Metadata>();
#endif
auto graph = scene.getGraph(true);
#if 1
for ( auto entity : graph ) entity->tick();
auto& tasks = metadata.tasks;
#else
pod::Thread::Tasks tasks = metadata.tasks;
tasks.queue([&]{
for ( auto entity : graph ) entity->tick();
});
#endif
uf::thread::execute( tasks );
}
void uf::scene::render() {
if ( scenes.empty() ) return;

View File

@ -102,10 +102,12 @@ void ext::opengl::CommandBuffer::submit() {
switch ( header->type ) {
case ext::opengl::enums::Command::CLEAR: {
InfoClear* info = (InfoClear*) header;
/*
GL_ERROR_CHECK(glClearColor(info->color[0], info->color[1], info->color[2], info->color[3]));
GL_ERROR_CHECK(glClearDepth(info->depth));
GL_ERROR_CHECK(glClear(info->bits));
// GL_ERROR_CHECK(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &info->color[0]));
GL_ERROR_CHECK(glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &info->color[0]));
*/
//UF_TIMER_MULTITRACE("Command::CLEAR");
} break;
case ext::opengl::enums::Command::VIEWPORT: {
@ -249,7 +251,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
if ( drawInfo.attributes.indirect.pointer && drawInfo.attributes.indirect.length == sizeof(pod::DrawCommand) ) {
pod::DrawCommand& drawCommand = *(pod::DrawCommand*) drawInfo.attributes.indirect.pointer;
if ( ext::opengl::settings::experimental::culling && drawInfo.attributes.instance.pointer && drawInfo.attributes.instance.length == sizeof(pod::Instance) ) {
if ( ext::opengl::settings::pipelines::culling && drawInfo.attributes.instance.pointer && drawInfo.attributes.instance.length == sizeof(pod::Instance) ) {
pod::Instance& instance = *(pod::Instance*) drawInfo.attributes.instance.pointer;
pod::Matrix4f mat = (*drawInfo.matrices.projection) * (*drawInfo.matrices.view) * (*drawInfo.matrices.model);
@ -266,6 +268,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION));
GL_ERROR_CHECK(glLoadMatrixf( &projection[0] ));
#if 1
if ( drawInfo.descriptor.cullMode == GL_NONE ) {
GL_ERROR_CHECK(glDisable(GL_CULL_FACE));
} else {
@ -279,6 +282,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glDisable(GL_DEPTH_TEST));
}
GL_ERROR_CHECK(glDepthMask(drawInfo.descriptor.depth.write ? GL_TRUE : GL_FALSE));
#endif
// CPU-buffer based command dispatching
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glEnableClientState(GL_NORMAL_ARRAY));
@ -294,10 +298,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GLboolean blending = glIsEnabled(GL_BLEND);
if ( drawInfo.textures.primary.image && drawInfo.attributes.uv.pointer ) {
// static GLuint previous = 0;
// if ( previous != drawInfo.textures.primary.image ) previous = drawInfo.textures.primary.image;
if ( drawInfo.textures.primary.image && drawInfo.attributes.uv.pointer ) {
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0));
@ -306,43 +307,41 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image));
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.uv.stride, (drawInfo.attributes.uv.pointer + drawInfo.attributes.uv.stride * drawInfo.descriptor.inputs.vertex.first)));
if ( drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer ) {
if ( !(drawInfo.textures.secondary.image && drawInfo.attributes.st.pointer) ) {
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
} else {
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE));
// static GLuint previous = 0;
// if ( previous != drawInfo.textures.secondary.image ) previous = drawInfo.textures.secondary.image;
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glEnable(drawInfo.textures.secondary.viewType));
GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, drawInfo.textures.secondary.image));
GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
#if UF_ENV_DREAMCAST
if ( blending ) GL_ERROR_CHECK(glDisable(GL_BLEND));
#endif
GL_ERROR_CHECK(glTexCoordPointer(2, GL_FLOAT, drawInfo.attributes.st.stride, (drawInfo.attributes.st.pointer + drawInfo.attributes.st.stride * drawInfo.descriptor.inputs.vertex.first)));
}
}
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glNormalPointer(GL_FLOAT, drawInfo.attributes.normal.stride, (drawInfo.attributes.normal.pointer + drawInfo.attributes.normal.stride * drawInfo.descriptor.inputs.vertex.first)));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glColorPointer(4, GL_UNSIGNED_BYTE, drawInfo.attributes.color.stride, (drawInfo.attributes.color.pointer + drawInfo.attributes.color.stride * drawInfo.descriptor.inputs.vertex.first)));
if ( drawInfo.attributes.color.pointer ) {
GLenum format = GL_UNSIGNED_BYTE;
switch ( drawInfo.attributes.color.descriptor.size / drawInfo.attributes.color.descriptor.components ) {
case sizeof(uint8_t): format = GL_UNSIGNED_BYTE; break;
case sizeof(float): format = GL_FLOAT; break;
}
GL_ERROR_CHECK(glColorPointer(drawInfo.attributes.color.descriptor.components, format, drawInfo.attributes.color.stride, (drawInfo.attributes.color.pointer + drawInfo.attributes.color.stride * drawInfo.descriptor.inputs.vertex.first)));
}
GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, drawInfo.attributes.position.stride, (drawInfo.attributes.position.pointer + drawInfo.attributes.position.stride * drawInfo.descriptor.inputs.vertex.first)));
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (drawInfo.attributes.index.pointer + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first)));
if ( drawInfo.textures.secondary.image ) {
#if UF_ENV_DREAMCAST
if ( blending ) GL_ERROR_CHECK(glEnable(GL_BLEND));
#endif
if ( drawInfo.descriptor.inputs.index.count ) {
GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, drawInfo.descriptor.inputs.index.count, indicesType, (drawInfo.attributes.index.pointer + drawInfo.attributes.index.stride * drawInfo.descriptor.inputs.index.first)));
} else {
GL_ERROR_CHECK(glDrawArrays(GL_TRIANGLES, drawInfo.descriptor.inputs.vertex.first, drawInfo.descriptor.inputs.vertex.count));
}
#if 0
if ( drawInfo.textures.secondary.image ) {
#if UF_ENV_DREAMCAST
GL_ERROR_CHECK(glEnable(GL_BLEND));
#endif
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE1));
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.secondary.viewType, 0));
@ -354,7 +353,6 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, 0));
GL_ERROR_CHECK(glDisable(drawInfo.textures.primary.viewType));
}
#endif
if ( drawInfo.attributes.normal.pointer ) GL_ERROR_CHECK(glDisableClientState(GL_NORMAL_ARRAY));
if ( drawInfo.attributes.color.pointer ) GL_ERROR_CHECK(glDisableClientState(GL_COLOR_ARRAY));

View File

@ -365,16 +365,18 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
CommandBuffer::InfoDraw drawCommandInfoBase = {};
drawCommandInfoBase.type = ext::opengl::enums::Command::DRAW;
drawCommandInfoBase.descriptor = descriptor;
drawCommandInfoBase.attributes.index = descriptor.inputs.index.attributes.front();
if ( descriptor.inputs.index.count ) {
drawCommandInfoBase.attributes.index = descriptor.inputs.index.attributes.front();
}
for ( uf::Mesh::Attribute attribute : descriptor.inputs.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) drawCommandInfoBase.attributes.position = attribute;
else if ( attribute.descriptor.name == "uv" ) drawCommandInfoBase.attributes.uv = attribute;
else if ( attribute.descriptor.name == "st" ) drawCommandInfoBase.attributes.st = attribute;
else if ( attribute.descriptor.name == "normal" ) drawCommandInfoBase.attributes.normal = attribute;
// else if ( attribute.descriptor.name == "normal" ) drawCommandInfoBase.attributes.normal = attribute;
else if ( attribute.descriptor.name == "color" ) drawCommandInfoBase.attributes.color = attribute;
}
drawCommandInfoBase.attributes.index = descriptor.inputs.index.attributes.front();
if ( uniformBufferSize == sizeof(pod::Camera::Viewports) ) {
drawCommandInfoBase.matrices.view = &viewports->matrices[0].view;
drawCommandInfoBase.matrices.projection = &viewports->matrices[0].projection;
@ -400,7 +402,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
pod::Material* materials = (pod::Material*) device->getBuffer( materialBuffer );
pod::Texture* textures = (pod::Texture*) device->getBuffer( textureBuffer );
const bool optimize = false;
// const bool optimize = false;
uf::stl::unordered_map<size_t, uf::stl::vector<CommandBuffer::InfoDraw>> pool;
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) {
auto& drawCommand = drawCommands[i];
@ -410,8 +412,8 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
auto& material = materials[materialID];
auto textureID = material.indexAlbedo;
auto& infos = pool[textureID];
CommandBuffer::InfoDraw& drawCommandInfo = infos.emplace_back( drawCommandInfoBase );
// CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase;
drawCommandInfo.descriptor.inputs.index.first = drawCommand.indexID;
drawCommandInfo.descriptor.inputs.index.count = drawCommand.indices;
@ -419,7 +421,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
drawCommandInfo.descriptor.inputs.vertex.first = drawCommand.vertexID;
drawCommandInfo.descriptor.inputs.vertex.count = drawCommand.vertices;
drawCommandInfo.attributes.instance.pointer = &instance;
drawCommandInfo.attributes.instance.length = sizeof(instance);
@ -440,14 +441,17 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
commandBuffer.record(drawCommandInfo);
}
} else {
/*
UF_MSG_DEBUG( viewports << " " << uniformBuffers.size() );
if ( drawCommandInfoBase.matrices.model ) UF_MSG_DEBUG( "model: " << drawCommandInfoBase.matrices.model << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.model ) );
if ( drawCommandInfoBase.matrices.view ) UF_MSG_DEBUG( "view: " << drawCommandInfoBase.matrices.view << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.view ) );
if ( drawCommandInfoBase.matrices.projection ) UF_MSG_DEBUG( "projection: " << drawCommandInfoBase.matrices.projection << " " << uf::matrix::toString( *drawCommandInfoBase.matrices.projection ) );
*/
CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase;
commandBuffer.record(drawCommandInfoBase);
drawCommandInfoBase.matrices.model = NULL;
drawCommandInfoBase.matrices.view = NULL;
drawCommandInfoBase.matrices.projection = NULL;
if ( !material.textures.empty() ) {
drawCommandInfo.textures.primary = material.textures.front().descriptor;
}
commandBuffer.record(drawCommandInfo);
}
}
void ext::opengl::Graphic::destroy() {
@ -485,7 +489,7 @@ ext::opengl::GraphicDescriptor::hash_t ext::opengl::GraphicDescriptor::hash() co
size_t hash{};
hash += std::hash<decltype(subpass)>{}(subpass);
if ( settings::experimental::individualPipelines )
if ( settings::invariant::individualPipelines )
hash += std::hash<decltype(renderMode)>{}(renderMode);
hash += std::hash<decltype(renderTarget)>{}(renderTarget);

View File

@ -27,21 +27,27 @@ uf::stl::vector<uf::stl::string> ext::opengl::settings::requestedInstanceExtensi
ext::opengl::enums::Filter::type_t ext::opengl::settings::swapchainUpscaleFilter = ext::opengl::enums::Filter::LINEAR;
// these go hand in hand for the above
bool ext::opengl::settings::experimental::dedicatedThread = false;
bool ext::opengl::settings::experimental::rebuildOnTickBegin = false;
bool ext::opengl::settings::experimental::waitOnRenderEnd = false;
bool ext::opengl::settings::experimental::individualPipelines = true;
bool ext::opengl::settings::experimental::multithreadedCommandRecording = true;
bool ext::opengl::settings::experimental::multithreadedCommandRendering = false;
uf::stl::string ext::opengl::settings::experimental::deferredMode = "";
bool ext::opengl::settings::experimental::deferredReconstructPosition = false;
bool ext::opengl::settings::experimental::deferredAliasOutputToSwapchain = true;
bool ext::opengl::settings::experimental::multiview = true;
bool ext::opengl::settings::experimental::vsync = true;
bool ext::opengl::settings::experimental::hdr = true;
bool ext::opengl::settings::experimental::vxgi = true;
bool ext::opengl::settings::experimental::deferredSampling = false;
bool ext::opengl::settings::experimental::culling = false;
bool ext::opengl::settings::experimental::bloom = false;
// not so experimental
bool ext::opengl::settings::invariant::waitOnRenderEnd = false;
bool ext::opengl::settings::invariant::individualPipelines = true;
bool ext::opengl::settings::invariant::multithreadedRecording = true;
uf::stl::string ext::opengl::settings::invariant::deferredMode = "";
bool ext::opengl::settings::invariant::deferredReconstructPosition = false;
bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = true;
bool ext::opengl::settings::invariant::deferredSampling = true;
bool ext::opengl::settings::invariant::multiview = true;
// pipelines
bool ext::opengl::settings::pipelines::vsync = true;
bool ext::opengl::settings::pipelines::hdr = true;
bool ext::opengl::settings::pipelines::vxgi = true;
bool ext::opengl::settings::pipelines::culling = false;
bool ext::opengl::settings::pipelines::bloom = false;
GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace;
ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM;
@ -56,9 +62,9 @@ std::mutex ext::opengl::immediateModeMutex;
bool ext::opengl::states::resized = false;
bool ext::opengl::states::rebuild = false;
uint32_t ext::opengl::states::currentBuffer = 0;
uf::ThreadUnique<ext::opengl::RenderMode*> ext::opengl::currentRenderMode;
uf::stl::vector<uf::Scene*> ext::opengl::scenes;
ext::opengl::RenderMode* ext::opengl::currentRenderMode = NULL;
uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::renderModes = {
new ext::opengl::BaseRenderMode,
};
@ -131,6 +137,18 @@ void UF_API ext::opengl::removeRenderMode( ext::opengl::RenderMode* mode, bool f
if ( free ) delete mode;
ext::opengl::states::rebuild = true;
}
ext::opengl::RenderMode* UF_API ext::opengl::getCurrentRenderMode() {
return getCurrentRenderMode( std::this_thread::get_id() );
}
ext::opengl::RenderMode* UF_API ext::opengl::getCurrentRenderMode( std::thread::id id ) {
return ext::opengl::currentRenderMode.get(id);
}
void UF_API ext::opengl::setCurrentRenderMode( ext::opengl::RenderMode* renderMode ) {
return setCurrentRenderMode( renderMode, std::this_thread::get_id() );
}
void UF_API ext::opengl::setCurrentRenderMode( ext::opengl::RenderMode* renderMode, std::thread::id id ) {
ext::opengl::currentRenderMode.get(id) = renderMode;
}
void UF_API ext::opengl::initialize() {
device.initialize();
@ -166,17 +184,18 @@ void UF_API ext::opengl::initialize() {
}
uf::graph::initialize();
pod::Thread::container_t jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( settings::experimental::individualPipelines ) renderMode->bindPipelines();
if ( settings::experimental::multithreadedCommandRecording ) {
jobs.emplace_back([&](){renderMode->createCommandBuffers();});
} else renderMode->createCommandBuffers();
auto tasks = uf::thread::schedule(settings::invariant::multithreadedRecording ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
tasks.queue([&]{
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
});
}
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
uf::thread::execute( tasks );
// bind shaders
#if 0
/*
{
ext::opengl::Shader::bind( uf::io::root + "shaders/graph/cull.comp.spv", []( const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic ) {
@ -186,7 +205,6 @@ void UF_API ext::opengl::initialize() {
});
}
*/
#if 0
{
ext::opengl::Shader::bind( uf::io::root + "shaders/graph/instanced.vert.spv", [](const ext::opengl::Shader& shader, const ext::opengl::Graphic& graphic, void* userdata) {
if ( !userdata ) return;
@ -338,16 +356,16 @@ void UF_API ext::opengl::tick(){
}
renderMode->tick();
}
pod::Thread::container_t jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( ext::opengl::states::rebuild || renderMode->rebuild ) {
if ( settings::experimental::individualPipelines ) renderMode->bindPipelines();
if ( settings::experimental::multithreadedCommandRecording ) jobs.emplace_back([&](){renderMode->createCommandBuffers();});
else renderMode->createCommandBuffers();
}
auto tasks = uf::thread::schedule(settings::invariant::multithreadedRecording ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
if ( ext::opengl::states::rebuild || renderMode->rebuild ) tasks.queue([&]{
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
});
}
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
uf::thread::execute( tasks );
/*
ext::opengl::device.activateContext();
ext::opengl::device.commandBuffer.end();
@ -362,12 +380,7 @@ void UF_API ext::opengl::tick(){
void UF_API ext::opengl::render(){
ext::opengl::mutex.lock();
#if !UF_ENV_DREAMCAST
#if 0
if ( hasRenderMode("Gui", true) ) {
RenderMode& primary = getRenderMode("Gui", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
#if 1
if ( hasRenderMode("", true) ) {
RenderMode& primary = getRenderMode("", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
@ -377,19 +390,66 @@ void UF_API ext::opengl::render(){
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
if ( hasRenderMode("Gui", true) ) {
RenderMode& primary = getRenderMode("Gui", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
#endif
ext::opengl::device.activateContext();
#endif
{
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadata = scene.getComponent<uf::Serializer>();
CommandBuffer::InfoClear clearCommandInfo = {};
clearCommandInfo.type = enums::Command::CLEAR;
clearCommandInfo.color = {1.0f, 1.0f, 1.0f, 1.0f};
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
clearCommandInfo.depth = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
#if 1
if ( !ext::json::isNull( sceneMetadata["system"]["renderer"]["clear values"][0] ) ) {
clearCommandInfo.color = uf::vector::decode( sceneMetadata["system"]["renderer"]["clear values"][0], pod::Vector4f{0,0,0,0} );
}
if ( !ext::json::isNull( sceneMetadata["light"]["ambient"] ) ) {
clearCommandInfo.color = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{0,0,0,0} );
// auto ambient = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{1,1,1,1} );
// GL_ERROR_CHECK(glLightfv(GL_LIGHT0, GL_AMBIENT, &ambient[0]));
}
#endif
GL_ERROR_CHECK(glClearColor(clearCommandInfo.color[0], clearCommandInfo.color[1], clearCommandInfo.color[2], clearCommandInfo.color[3]));
GL_ERROR_CHECK(glClearDepth(clearCommandInfo.depth));
GL_ERROR_CHECK(glClear(clearCommandInfo.bits));
}
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute ) continue;
ext::opengl::currentRenderMode = renderMode;
ext::opengl::setCurrentRenderMode( renderMode );
uf::graph::render();
uf::scene::render();
renderMode->render();
renderMode->executed = true;
ext::opengl::setCurrentRenderMode(NULL);
}
ext::opengl::currentRenderMode = NULL;
if ( ext::opengl::settings::experimental::waitOnRenderEnd ) synchronize();
if ( ext::opengl::settings::invariant::waitOnRenderEnd ) synchronize();
{
#if UF_ENV_DREAMCAST
#if UF_USE_OPENGL_GLDC
glKosSwapBuffers();
#else
glutSwapBuffers();
#endif
#else
device.activateContext().display();
#endif
}
#if UF_USE_OPENVR
// if ( ext::openvr::context ) ext::openvr::postSubmit();
#endif

View File

@ -130,6 +130,8 @@ void ext::opengl::RenderMode::render() {
auto& commands = getCommands(this->mostRecentCommandPoolId);
commands.submit();
this->executed = true;
#if 0
if ( ext::opengl::renderModes.back() != this ) return;
#if UF_ENV_DREAMCAST
@ -141,6 +143,7 @@ void ext::opengl::RenderMode::render() {
#else
if ( device ) device->activateContext().display();
#endif
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadata = scene.getComponent<uf::Serializer>();
@ -161,7 +164,7 @@ void ext::opengl::RenderMode::render() {
GL_ERROR_CHECK(glClearColor(clearCommandInfo.color[0], clearCommandInfo.color[1], clearCommandInfo.color[2], clearCommandInfo.color[3]));
GL_ERROR_CHECK(glClearDepth(clearCommandInfo.depth));
GL_ERROR_CHECK(glClear(clearCommandInfo.bits));
#endif
}
void ext::opengl::RenderMode::initialize( Device& device ) {

View File

@ -41,12 +41,12 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
}
commands.record(clearCommandInfo);
#endif
CommandBuffer::InfoViewport viewportCommandInfo = {};
viewportCommandInfo.type = enums::Command::VIEWPORT;
viewportCommandInfo.corner = pod::Vector2ui{0, 0};
viewportCommandInfo.size = pod::Vector2ui{width, height};
commands.record(viewportCommandInfo);
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != "" ) continue;
GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass );
@ -71,10 +71,13 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) {
}
GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST));
GL_ERROR_CHECK(glEnable(GL_TEXTURE_2D));
GL_ERROR_CHECK(glEnable(GL_ALPHA_TEST));
GL_ERROR_CHECK(glAlphaFunc(GL_GREATER, 0.1f));
GL_ERROR_CHECK(glEnable(GL_BLEND));
GL_ERROR_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
GL_ERROR_CHECK(glEnable(GL_LIGHTING));
// GL_ERROR_CHECK(glEnable(GL_LIGHTING));
// GL_ERROR_CHECK(glEnable(GL_NORMALIZE));
// GL_ERROR_CHECK(glEnable(GL_COLOR_MATERIAL));
@ -103,8 +106,6 @@ void ext::opengl::BaseRenderMode::tick() {
ext::opengl::RenderMode::tick();
}
void ext::opengl::BaseRenderMode::render() {
// if ( ext::opengl::renderModes.size() > 1 ) return;
// if ( ext::opengl::renderModes.back() != this ) return;
ext::opengl::RenderMode::render();
}

View File

@ -1,49 +0,0 @@
#if UF_USE_OPENGL
#include <uf/ext/opengl/opengl.h>
#include <uf/ext/opengl/rendermodes/compute.h>
#include <uf/ext/opengl/rendermodes/deferred.h>
#include <uf/ext/opengl/rendermodes/rendertarget.h>
#include <uf/ext/opengl/initializers.h>
#include <uf/ext/openvr/openvr.h>
#include <uf/utils/window/window.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/opengl/graphic.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/math/transform.h>
#include <uf/ext/opengl/graphic.h>
const uf::stl::string ext::opengl::ComputeRenderMode::getType() const {
return "Compute";
}
const size_t ext::opengl::ComputeRenderMode::blitters() const {
return 1;
}
ext::opengl::Graphic* ext::opengl::ComputeRenderMode::getBlitter( size_t i ) {
return &this->blitter;
}
uf::stl::vector<ext::opengl::Graphic*> ext::opengl::ComputeRenderMode::getBlitters() {
return { &this->blitter };
}
void ext::opengl::ComputeRenderMode::initialize( Device& device ) {
ext::opengl::RenderMode::initialize( device );
}
void ext::opengl::ComputeRenderMode::render() {
}
void ext::opengl::ComputeRenderMode::tick() {
ext::opengl::RenderMode::tick();
}
void ext::opengl::ComputeRenderMode::destroy() {
ext::opengl::RenderMode::destroy();
}
void ext::opengl::ComputeRenderMode::pipelineBarrier( GLhandle(VkCommandBuffer) commandBuffer, uint8_t state ) {
}
void ext::opengl::ComputeRenderMode::createCommandBuffers( ) {
}
void ext::opengl::ComputeRenderMode::bindPipelines() {
}
#endif

View File

@ -34,6 +34,9 @@ void ext::opengl::DeferredRenderMode::initialize( Device& device ) {
void ext::opengl::DeferredRenderMode::tick() {
ext::opengl::RenderMode::tick();
}
void ext::opengl::DeferredRenderMode::render() {
ext::opengl::RenderMode::render();
}
void ext::opengl::DeferredRenderMode::destroy() {
ext::opengl::RenderMode::destroy();
}

View File

@ -82,7 +82,7 @@ void ext::opengl::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
commands.record(clearCommandInfo);
#endif
#if 0
#if 1
CommandBuffer::InfoViewport viewportCommandInfo = {};
viewportCommandInfo.type = enums::Command::VIEWPORT;
viewportCommandInfo.corner = pod::Vector2ui{0, 0};

View File

@ -467,7 +467,9 @@ void ext::openvr::submit() { bool invert = swapEyes;
#endif
}
void ext::openvr::synchronize( bool async ) {
if ( async ) uf::thread::add( uf::thread::fetchWorker(), [](){ vr::VRCompositor()->WaitGetPoses(nullptr, 0, nullptr, 0); return true; }, true );
if ( async ) uf::thread::queue( uf::thread::fetchWorker(), [](){
vr::VRCompositor()->WaitGetPoses(nullptr, 0, nullptr, 0);
});
else vr::VRCompositor()->WaitGetPoses(nullptr, 0, nullptr, 0);
ext::openvr::updateTracking(1);

View File

@ -220,10 +220,18 @@ void ext::reactphysics::tick( float delta ) {
accumulator += uf::physics::time::delta;
#if 0
delta = delta * ext::reactphysics::timescale / 12;
for ( size_t i = 0; i < 12; ++i ) {
::world->update(ext::reactphysics::timescale);
accumulator -= delta;
}
#else
while ( accumulator >= ext::reactphysics::timescale ) {
::world->update(ext::reactphysics::timescale);
accumulator -= ext::reactphysics::timescale;
}
#endif
TIMER(ext::reactphysics::debugDraw::rate, ext::reactphysics::debugDraw::enabled && ) {
auto& scene = uf::scene::getCurrentScene();

View File

@ -263,10 +263,109 @@ int ext::vulkan::Device::rate( VkPhysicalDevice device ) {
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
int score = 0;
// Discrete GPUs have a significant performance advantage
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
score += 1000;
// Maximum possible size of textures affects graphics quality
score += deviceProperties.limits.maxImageDimension2D;
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) score += 1000;
{
score += deviceProperties.limits.maxImageDimension1D;
score += deviceProperties.limits.maxImageDimension2D;
score += deviceProperties.limits.maxImageDimension3D;
score += deviceProperties.limits.maxImageDimensionCube;
score += deviceProperties.limits.maxImageArrayLayers;
score += deviceProperties.limits.maxTexelBufferElements;
score += deviceProperties.limits.maxUniformBufferRange;
score += deviceProperties.limits.maxStorageBufferRange;
score += deviceProperties.limits.maxPushConstantsSize;
score += deviceProperties.limits.maxMemoryAllocationCount;
score += deviceProperties.limits.maxSamplerAllocationCount;
score += deviceProperties.limits.bufferImageGranularity;
score += deviceProperties.limits.sparseAddressSpaceSize;
score += deviceProperties.limits.maxBoundDescriptorSets;
score += deviceProperties.limits.maxPerStageDescriptorSamplers;
score += deviceProperties.limits.maxPerStageDescriptorUniformBuffers;
score += deviceProperties.limits.maxPerStageDescriptorStorageBuffers;
score += deviceProperties.limits.maxPerStageDescriptorSampledImages;
score += deviceProperties.limits.maxPerStageDescriptorStorageImages;
score += deviceProperties.limits.maxPerStageDescriptorInputAttachments;
score += deviceProperties.limits.maxPerStageResources;
score += deviceProperties.limits.maxDescriptorSetSamplers;
score += deviceProperties.limits.maxDescriptorSetUniformBuffers;
score += deviceProperties.limits.maxDescriptorSetUniformBuffersDynamic;
score += deviceProperties.limits.maxDescriptorSetStorageBuffers;
score += deviceProperties.limits.maxDescriptorSetStorageBuffersDynamic;
score += deviceProperties.limits.maxDescriptorSetSampledImages;
score += deviceProperties.limits.maxDescriptorSetStorageImages;
score += deviceProperties.limits.maxDescriptorSetInputAttachments;
score += deviceProperties.limits.maxVertexInputAttributes;
score += deviceProperties.limits.maxVertexInputBindings;
score += deviceProperties.limits.maxVertexInputAttributeOffset;
score += deviceProperties.limits.maxVertexInputBindingStride;
score += deviceProperties.limits.maxVertexOutputComponents;
score += deviceProperties.limits.maxTessellationGenerationLevel;
score += deviceProperties.limits.maxTessellationPatchSize;
score += deviceProperties.limits.maxTessellationControlPerVertexInputComponents;
score += deviceProperties.limits.maxTessellationControlPerVertexOutputComponents;
score += deviceProperties.limits.maxTessellationControlPerPatchOutputComponents;
score += deviceProperties.limits.maxTessellationControlTotalOutputComponents;
score += deviceProperties.limits.maxTessellationEvaluationInputComponents;
score += deviceProperties.limits.maxTessellationEvaluationOutputComponents;
score += deviceProperties.limits.maxGeometryShaderInvocations;
score += deviceProperties.limits.maxGeometryInputComponents;
score += deviceProperties.limits.maxGeometryOutputComponents;
score += deviceProperties.limits.maxGeometryOutputVertices;
score += deviceProperties.limits.maxGeometryTotalOutputComponents;
score += deviceProperties.limits.maxFragmentInputComponents;
score += deviceProperties.limits.maxFragmentOutputAttachments;
score += deviceProperties.limits.maxFragmentDualSrcAttachments;
score += deviceProperties.limits.maxFragmentCombinedOutputResources;
score += deviceProperties.limits.maxComputeSharedMemorySize;
score += deviceProperties.limits.maxComputeWorkGroupInvocations;
score += deviceProperties.limits.subPixelPrecisionBits;
score += deviceProperties.limits.subTexelPrecisionBits;
score += deviceProperties.limits.mipmapPrecisionBits;
score += deviceProperties.limits.maxDrawIndexedIndexValue;
score += deviceProperties.limits.maxDrawIndirectCount;
score += deviceProperties.limits.maxSamplerLodBias;
score += deviceProperties.limits.maxSamplerAnisotropy;
score += deviceProperties.limits.maxViewports;
score += deviceProperties.limits.viewportSubPixelBits;
score += deviceProperties.limits.minMemoryMapAlignment;
score += deviceProperties.limits.minTexelBufferOffsetAlignment;
score += deviceProperties.limits.minUniformBufferOffsetAlignment;
score += deviceProperties.limits.minStorageBufferOffsetAlignment;
score += deviceProperties.limits.minTexelOffset;
score += deviceProperties.limits.maxTexelOffset;
score += deviceProperties.limits.minTexelGatherOffset;
score += deviceProperties.limits.maxTexelGatherOffset;
score += deviceProperties.limits.minInterpolationOffset;
score += deviceProperties.limits.maxInterpolationOffset;
score += deviceProperties.limits.subPixelInterpolationOffsetBits;
score += deviceProperties.limits.maxFramebufferWidth;
score += deviceProperties.limits.maxFramebufferHeight;
score += deviceProperties.limits.maxFramebufferLayers;
score += deviceProperties.limits.framebufferColorSampleCounts;
score += deviceProperties.limits.framebufferDepthSampleCounts;
score += deviceProperties.limits.framebufferStencilSampleCounts;
score += deviceProperties.limits.framebufferNoAttachmentsSampleCounts;
score += deviceProperties.limits.maxColorAttachments;
score += deviceProperties.limits.sampledImageColorSampleCounts;
score += deviceProperties.limits.sampledImageIntegerSampleCounts;
score += deviceProperties.limits.sampledImageDepthSampleCounts;
score += deviceProperties.limits.sampledImageStencilSampleCounts;
score += deviceProperties.limits.storageImageSampleCounts;
score += deviceProperties.limits.maxSampleMaskWords;
score += deviceProperties.limits.timestampComputeAndGraphics;
score += deviceProperties.limits.timestampPeriod;
score += deviceProperties.limits.maxClipDistances;
score += deviceProperties.limits.maxCullDistances;
score += deviceProperties.limits.maxCombinedClipAndCullDistances;
score += deviceProperties.limits.discreteQueuePriorities;
score += deviceProperties.limits.pointSizeGranularity;
score += deviceProperties.limits.lineWidthGranularity;
score += deviceProperties.limits.strictLines;
score += deviceProperties.limits.standardSampleLocations;
score += deviceProperties.limits.optimalBufferCopyOffsetAlignment;
score += deviceProperties.limits.optimalBufferCopyRowPitchAlignment;
score += deviceProperties.limits.nonCoherentAtomSize;
}
// Application can't function without geometry shaders
if ( !deviceFeatures.geometryShader ) return 0;
//
@ -307,6 +406,10 @@ int ext::vulkan::Device::rate( VkPhysicalDevice device ) {
}
if ( formats.empty() || presentModes.empty() ) return 0;
}
if ( settings::gpuID != -1 && deviceProperties.deviceID == settings::gpuID ) {
score = std::numeric_limits<int>::max();
}
UF_MSG_VALIDATION("Device name: " << deviceProperties.deviceName << " (" << deviceProperties.deviceID << ") has a score of " << score);
return score;
}
@ -605,6 +708,16 @@ void ext::vulkan::Device::initialize() {
uf::stl::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices( this->instance, &deviceCount, devices.data() );
int bestScore = 0;
for ( const VkPhysicalDevice& device : devices ) {
int score = rate( device );
if ( score <= bestScore ) continue;
bestScore = score;
physicalDevice = device;
}
/*
// Use an ordered map to automatically sort candidates by increasing score
std::multimap<int, VkPhysicalDevice> candidates;
for ( const VkPhysicalDevice& device : devices ) {
@ -614,6 +727,7 @@ void ext::vulkan::Device::initialize() {
// Check if the best candidate is suitable at all
if ( candidates.rbegin()->first <= 0 ) UF_EXCEPTION("Vulkan error: failed to find a suitable GPU!");
this->physicalDevice = candidates.rbegin()->second;
*/
}
// Update properties
{
@ -624,6 +738,7 @@ void ext::vulkan::Device::initialize() {
// Memory properties are used regularly for creating all kinds of buffers
vkGetPhysicalDeviceMemoryProperties( this->physicalDevice, &memoryProperties );
}
UF_MSG_VALIDATION("Using device " << properties.deviceName << " (" << properties.deviceID << ")");
{
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@ -856,7 +971,7 @@ void ext::vulkan::Device::initialize() {
bool SRGB = true;
auto TARGET_FORMAT = SRGB ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
auto TARGET_COLORSPACE = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
if ( ext::vulkan::settings::experimental::hdr ) {
if ( ext::vulkan::settings::pipelines::hdr ) {
TARGET_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
TARGET_COLORSPACE = VK_COLOR_SPACE_HDR10_ST2084_EXT;
}

View File

@ -280,9 +280,9 @@ void ext::vulkan::Pipeline::initialize( const Graphic& graphic, const GraphicDes
PIPELINE_INITIALIZATION_INVALID:
VK_DEBUG_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
uf::thread::queue( uf::thread::get("Main"), [&]{
this->initialize( graphic, descriptor );
return 0;}, true );
});
return;
}
void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) const {
@ -376,9 +376,24 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
for ( auto* shader : shaders ) {
auto& infos = INFOS.emplace_back();
uf::stl::vector<ext::vulkan::enums::Image::viewType_t> types;
// add per-rendermode buffers
for ( auto& buffer : renderMode.buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
}
// add per-shader buffers
for ( auto& buffer : shader->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
}
// add per-pipeline buffers
for ( auto& buffer : this->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
}
if ( descriptor.subpass < renderTarget.passes.size() ) {
auto& subpass = renderTarget.passes[descriptor.subpass];
for ( auto& input : subpass.inputs ) {
@ -404,13 +419,8 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
infos.sampler.emplace_back(sampler.descriptor.info);
}
size_t consumes = 0;
for ( auto& buffer : shader->buffers ) {
if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) infos.uniform.emplace_back(buffer.descriptor);
if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) infos.storage.emplace_back(buffer.descriptor);
}
// check if we can even consume that many infos
size_t consumes = 0;
for ( auto& layout : shader->descriptorSetLayoutBindings ) {
switch ( layout.descriptorType ) {
// consume an texture image info
@ -635,9 +645,9 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
PIPELINE_UPDATE_INVALID:
// graphic.process = false;
VK_DEBUG_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick...");
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
uf::thread::queue( uf::thread::get("Main"), [&]{
this->update( graphic, descriptor );
return 0;}, true );
});
return;
}
void ext::vulkan::Pipeline::destroy() {
@ -659,6 +669,8 @@ void ext::vulkan::Pipeline::destroy() {
vkDestroyDescriptorSetLayout( *device, descriptorSetLayout, nullptr );
descriptorSetLayout = VK_NULL_HANDLE;
}
if ( settings::experimental::dedicatedThread ) ext::vulkan::states::rebuild = true;
}
uf::stl::vector<ext::vulkan::Shader*> ext::vulkan::Pipeline::getShaders( uf::stl::vector<ext::vulkan::Shader>& shaders ) {
uf::stl::unordered_map<uf::stl::string, ext::vulkan::Shader*> map;
@ -1103,7 +1115,7 @@ ext::vulkan::GraphicDescriptor::hash_t ext::vulkan::GraphicDescriptor::hash() co
size_t hash{};
hash += std::hash<decltype(subpass)>{}(subpass);
if ( settings::experimental::individualPipelines )
if ( settings::invariant::individualPipelines )
hash += std::hash<decltype(renderMode)>{}(renderMode);
hash += std::hash<decltype(renderTarget)>{}(renderTarget);

View File

@ -196,7 +196,11 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
this->synchronize();
// bindPipelines( graphics );
//lockMutex();
createCommandBuffers( graphics );
//unlockMutex();
this->mostRecentCommandPoolId = std::this_thread::get_id();
this->rebuild = false;
}
@ -219,6 +223,18 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma
}
return commands;
}
void ext::vulkan::RenderMode::lockMutex() {
return lockMutex( std::this_thread::get_id() );
}
void ext::vulkan::RenderMode::lockMutex( std::thread::id id ) {
this->commands.lock( id );
}
void ext::vulkan::RenderMode::unlockMutex() {
return unlockMutex( std::this_thread::get_id() );
}
void ext::vulkan::RenderMode::unlockMutex( std::thread::id id ) {
this->commands.unlock( id );
}
void ext::vulkan::RenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
}
@ -239,6 +255,7 @@ void ext::vulkan::RenderMode::bindPipelines() {
this->bindPipelines( graphics );
}
void ext::vulkan::RenderMode::bindPipelines( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
//lockMutex();
for ( auto* pointer : graphics ) {
auto& graphic = *pointer;
for ( size_t currentPass = 0; currentPass < renderTarget.passes.size(); ++currentPass ) {
@ -261,39 +278,23 @@ void ext::vulkan::RenderMode::bindPipelines( const uf::stl::vector<ext::vulkan::
}
}
}
//unlockMutex();
}
VkSubmitInfo ext::vulkan::RenderMode::queue() {
if ( !metadata.limiter.execute ) return {};
void ext::vulkan::RenderMode::render() {
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]);
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT )));
return submitInfo;
}
void ext::vulkan::RenderMode::initialize( Device& device ) {
@ -338,6 +339,10 @@ void ext::vulkan::RenderMode::tick() {
this->synchronize();
}
void ext::vulkan::RenderMode::render() {
this->synchronize();
}
void ext::vulkan::RenderMode::destroy() {
this->synchronize();
@ -360,9 +365,13 @@ void ext::vulkan::RenderMode::destroy() {
fences.clear();
}
void ext::vulkan::RenderMode::synchronize( uint64_t timeout ) {
/*
if ( !device ) return;
if ( fences.empty() ) return;
lockMutex();
VK_CHECK_RESULT(vkWaitForFences( *device, fences.size(), fences.data(), VK_TRUE, timeout ));
unlockMutex();
*/
}
void ext::vulkan::RenderMode::pipelineBarrier( VkCommandBuffer command, uint8_t stage ) {
}

View File

@ -94,7 +94,42 @@ void ext::vulkan::BaseRenderMode::tick() {
void ext::vulkan::BaseRenderMode::render() {
// if ( ext::vulkan::renderModes.size() > 1 ) return;
if ( ext::vulkan::renderModes.back() != this ) return;
ext::vulkan::RenderMode::render();
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]);
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT )));
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::BaseRenderMode::initialize( Device& device ) {

View File

@ -1,260 +0,0 @@
#if UF_USE_VULKAN
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/rendermodes/deferred.h>
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
#include <uf/ext/vulkan/initializers.h>
#include <uf/ext/openvr/openvr.h>
#include <uf/utils/window/window.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/math/transform.h>
#include <uf/ext/vulkan/graphic.h>
const uf::stl::string ext::vulkan::ComputeRenderMode::getType() const {
return "Compute";
}
const size_t ext::vulkan::ComputeRenderMode::blitters() const {
return 1;
}
ext::vulkan::Graphic* ext::vulkan::ComputeRenderMode::getBlitter( size_t i ) {
return &this->blitter;
}
uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::ComputeRenderMode::getBlitters() {
return { &this->blitter };
}
void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
ext::vulkan::RenderMode::initialize( device );
// this->width = 3840;
// this->height = 2160;
{
auto width = this->width > 0 ? this->width : ext::vulkan::settings::width;
auto height = this->height > 0 ? this->height : ext::vulkan::settings::height;
compute.device = &device;
compute.material.device = &device;
compute.descriptor.renderMode = this->getName();
compute.material.initializeShaders({
{uf::io::root+"/shaders/raytracing/comp.spv", VK_SHADER_STAGE_COMPUTE_BIT},
});
#if UF_USE_OPENVR
size_t eyes = (ext::openvr::context ? 2 : 1);
#else
size_t eyes = 1;
#endif
for ( size_t i = 0; i < eyes; ++i ) {
Texture2D& texture = compute.material.textures.emplace_back();
texture.asRenderTarget( device, width, height );
}
{
auto& scene = uf::scene::getCurrentScene();
auto& metadata = scene.getComponent<uf::Serializer>();
auto& shader = compute.material.shaders.front();
struct SpecializationConstant {
uint32_t maxLights = 16;
uint32_t eyes = 2;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
specializationConstants.eyes = eyes;
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 ) {
binding.descriptorCount = specializationConstants.eyes;
}
}
}
// update buffers
if ( !compute.buffers.empty() ) {
// compute.getPipeline().update( compute );
compute.updatePipelines();
}
}
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_2F2F, uint16_t>();
mesh.insertVertices<pod::Vertex_2F2F>({
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
});
mesh.insertIndices<uint16_t>({
0, 1, 2, 2, 3, 0
});
/*
uf::Mesh<pod::Vertex_2F2F, uint16_t> mesh;
mesh.vertices = {
{ {-1.0f, 1.0f}, {0.0f, 1.0f}, },
{ {-1.0f, -1.0f}, {0.0f, 0.0f}, },
{ {1.0f, -1.0f}, {1.0f, 0.0f}, },
{ {1.0f, 1.0f}, {1.0f, 1.0f}, }
};
mesh.indices = {
0, 1, 2, 2, 3, 0
};
*/
blitter.device = &device;
blitter.material.device = &device;
blitter.descriptor.subpass = 1;
blitter.descriptor.inputs.dispatch = { (width / 32) + 1, (height / 32) + 1, 1 };
blitter.descriptor.depth.test = false;
blitter.descriptor.depth.write = false;
blitter.initializeMesh( mesh );
blitter.material.initializeShaders({
{uf::io::root+"/shaders/display/blit.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
{uf::io::root+"/shaders/display/blit.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
});
for ( auto& computeTexture : compute.material.textures ) {
Texture2D& texture = blitter.material.textures.emplace_back();
texture = computeTexture;
texture.device = NULL;
}
blitter.initializePipeline();
}
}
void ext::vulkan::ComputeRenderMode::render() {
if ( compute.buffers.empty() ) return;
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit compute commands
// Use a fence to ensure that compute command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = ext::vulkan::initializers::submitInfo();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commands[states::currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer]));
//vkQueueSubmit(device->queues.compute, 1, &submitInfo, fences[states::currentBuffer]);
}
void ext::vulkan::ComputeRenderMode::tick() {
ext::vulkan::RenderMode::tick();
#if UF_USE_OPENVR
size_t eyes = (ext::openvr::context ? 2 : 1);
#else
size_t eyes = 1;
#endif
if ( ext::vulkan::states::resized ) {
// auto-resize texture
if ( this->width == 0 && this->height == 0 ) {
auto width = this->width > 0 ? this->width : ext::vulkan::settings::width;
auto height = this->height > 0 ? this->height : ext::vulkan::settings::height;
for ( auto& texture : compute.material.textures ) {
texture.destroy();
}
compute.material.textures.clear();
for ( size_t i = 0; i < eyes; ++i ) {
Texture2D& texture = compute.material.textures.emplace_back();
texture.asRenderTarget( *device, width, height );
}
}
// update blitter descriptor set
if ( blitter.initialized ) {
blitter.material.textures.clear();
for ( auto& computeTexture : compute.material.textures ) {
Texture2D& texture = blitter.material.textures.emplace_back();
texture = computeTexture;
texture.device = NULL;
}
blitter.getPipeline().update( blitter );
// blitter.updatePipelines();
}
if ( !compute.buffers.empty() ) {
compute.getPipeline().update( compute );
// compute.updatePipelines();
}
}
}
void ext::vulkan::ComputeRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
blitter.destroy();
compute.destroy();
}
void ext::vulkan::ComputeRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
if ( compute.buffers.empty() ) return;
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
for ( auto& texture : compute.material.textures ) {
VkPipelineStageFlags srcStageMask, dstStageMask;
imageMemoryBarrier.image = texture.image;
imageMemoryBarrier.oldLayout = texture.descriptor.imageLayout;
imageMemoryBarrier.newLayout = texture.descriptor.imageLayout;
switch ( state ) {
case 0: {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} break;
case 1: {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
} break;
// ensure
default: {
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
}
vkCmdPipelineBarrier( commandBuffer,
srcStageMask, dstStageMask,
VK_FLAGS_NONE,
0, NULL,
0, NULL,
1, &imageMemoryBarrier
);
texture.descriptor.imageLayout = imageMemoryBarrier.newLayout;
}
}
void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) {
this->synchronize();
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo();
auto& pipeline = compute.getPipeline();
auto& commands = getCommands();
if ( compute.buffers.empty() ) return;
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
pipeline.record(compute, commands[i]);
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
this->mostRecentCommandPoolId = std::this_thread::get_id();
}
void ext::vulkan::ComputeRenderMode::bindPipelines() {
}
#endif

View File

@ -34,11 +34,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain");
if ( swapchainRender.renderTarget.width != width || swapchainRender.renderTarget.height != height ) {
settings::experimental::deferredAliasOutputToSwapchain = false;
settings::invariant::deferredAliasOutputToSwapchain = false;
}
}
if ( settings::experimental::bloom ) settings::experimental::deferredAliasOutputToSwapchain = false;
// buffers.emplace_back().initialize( NULL, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
if ( settings::pipelines::bloom ) settings::invariant::deferredAliasOutputToSwapchain = false;
auto HDR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
auto SDR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
@ -52,7 +54,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
size_t id, normals, uvs, mips, albedo, depth, color, bright, scratch, output;
} attachments = {};
bool blend = true; // !ext::vulkan::settings::experimental::deferredSampling;
bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling;
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -68,7 +70,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredSampling ) {
if ( ext::vulkan::settings::invariant::deferredSampling ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
// /*.format = */VK_FORMAT_R32G32B32A32_SFLOAT,
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
@ -87,7 +89,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : VK_FORMAT_R8G8B8A8_UNORM,
/*.format = */ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */blend,
@ -102,21 +104,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.samples = */msaa,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ blend,
@ -124,7 +126,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
});
// Attach swapchain's image as output
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
if ( settings::invariant::deferredAliasOutputToSwapchain ) {
attachments.output = renderTarget.attachments.size();
auto& swapchainAttachment = renderTarget.attachments.emplace_back();
swapchainAttachment.descriptor.format = ext::vulkan::settings::formats::color; //device.formats.color;
@ -150,7 +152,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
} else {
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::experimental::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ blend,
@ -161,7 +163,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
// metadata.outputs.emplace_back(attachments.output);
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
if ( ext::vulkan::settings::experimental::deferredSampling ) {
if ( ext::vulkan::settings::invariant::deferredSampling ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
@ -242,9 +244,9 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/subpass.vert.spv";
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/subpass.frag.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::experimental::vxgi, "vxgi.frag" },
{ uf::renderer::settings::pipelines::vxgi, "vxgi.frag" },
{ msaa > 1, "msaa.frag" },
{ uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
{ uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
}
@ -257,7 +259,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
if ( settings::experimental::bloom ) {
if ( settings::pipelines::bloom ) {
uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom.comp.spv");
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom");
@ -288,7 +290,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
if ( ext::vulkan::settings::experimental::vxgi ) {
if ( ext::vulkan::settings::pipelines::vxgi ) {
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
@ -330,7 +332,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1;
if ( !blitter.hasPipeline( descriptor ) ) blitter.initializePipeline( descriptor );
if ( settings::experimental::bloom ) {
if ( settings::pipelines::bloom ) {
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
descriptor.subpass = 0;
@ -350,7 +352,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
if ( resized ) {
renderTarget.initialize( *renderTarget.device );
if ( settings::experimental::bloom ) {
if ( settings::pipelines::bloom ) {
auto& shader = blitter.material.getShader("compute", "bloom");
#if 1
shader.textures.clear();
@ -371,7 +373,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1;
if ( blitter.hasPipeline( blitter.descriptor ) ) blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
if ( settings::experimental::bloom ) {
if ( settings::pipelines::bloom ) {
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
descriptor.subpass = 0;
@ -382,6 +384,61 @@ void ext::vulkan::DeferredRenderMode::tick() {
}
}
}
VkSubmitInfo ext::vulkan::DeferredRenderMode::queue() {
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
static VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
return submitInfo;
}
void ext::vulkan::DeferredRenderMode::render() {
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapchain.acquireNextImage(&states::currentBuffer, swapchain.presentCompleteSemaphore));
// Use a fence to wait until the command buffer has finished execution before using it again
VK_CHECK_RESULT(vkWaitForFences(*device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(*device, 1, &fences[states::currentBuffer]));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = &swapchain.presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 1; // One wait semaphore
submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
// Submit to the graphics queue passing a wait fence
VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[states::currentBuffer]);
// Present the current buffer to the swap chain
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
// This ensures that the image is not presented to the windowing system until all commands have been submitted
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), states::currentBuffer, renderCompleteSemaphore));
VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT )));
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::DeferredRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
blitter.destroy();
@ -536,7 +593,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i] );
if ( settings::experimental::bloom ) {
if ( settings::pipelines::bloom ) {
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
@ -591,7 +648,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
layer->pipelineBarrier( commands[i], 1 );
}
if ( !settings::experimental::deferredAliasOutputToSwapchain ) {
if ( !settings::invariant::deferredAliasOutputToSwapchain ) {
{
auto& renderTarget = swapchainRender.renderTarget;
float width = renderTarget.width;

View File

@ -8,6 +8,7 @@
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/graph/graph.h>
#include <uf/utils/camera/camera.h>
const uf::stl::string ext::vulkan::RenderTargetRenderMode::getTarget() const {
// auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
@ -60,6 +61,12 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
if ( metadata.subpasses == 0 ) metadata.subpasses = 1;
renderTarget.device = &device;
renderTarget.views = metadata.views;
//
if ( metadata.type == "depth" ) {
buffers.emplace_back().initialize( NULL, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM );
}
if ( metadata.type == "depth" || metadata.type == "vxgi" ) {
renderTarget.views = metadata.subpasses;
struct {
@ -86,28 +93,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
}
} else {
for ( size_t currentPass = 0; currentPass < metadata.subpasses; ++currentPass ) {
if ( metadata.type == "depth" || metadata.type == "vxgi" ) {
struct {
size_t depth;
} attachments = {};
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,
/*.blend = */ false,
/*.samples = */ 1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{},
{},
{},
attachments.depth,
0,
true
);
} else if ( metadata.type == "single" ) {
if ( metadata.type == "single" ) {
struct {
size_t albedo, depth;
} attachments = {};
@ -136,62 +122,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
true
);
} else {
#if 0
struct {
size_t albedo, normals, position, depth;
} attachments = {};
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::color,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ true,
/*.samples = */ 1,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::normal,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.samples = */ 1,
});
if ( !settings::experimental::deferredReconstructPosition )
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ ext::vulkan::settings::formats::position,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */ false,
/*.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,
/*.blend = */ false,
/*.samples = */ 1,
});
// First pass: write to target
if ( settings::experimental::deferredReconstructPosition ) {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals },
{},
{},
attachments.depth
);
} else {
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{ attachments.albedo, attachments.normals, attachments.position },
{},
{},
attachments.depth
);
}
#else
struct {
size_t id, normals, uvs, albedo, depth, output;
} attachments = {};
@ -210,7 +140,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
if ( !true && ext::vulkan::settings::experimental::deferredMode != "" ) {
if ( !true && ext::vulkan::settings::invariant::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -241,7 +171,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( !true && ext::vulkan::settings::experimental::deferredMode != "" ) {
if ( !true && ext::vulkan::settings::invariant::deferredMode != "" ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
@ -293,7 +223,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
}
}
metadata.outputs.emplace_back(attachments.output);
#endif
}
}
}
@ -373,7 +302,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
std::pair<bool, uf::stl::string> settings[] = {
{ msaa > 1, "msaa.frag" },
// I don't actually have support for deferred sampling within a render target
// { uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
// { uf::renderer::settings::invariant::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
}
@ -514,12 +443,7 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
}
}
}
}
void ext::vulkan::RenderTargetRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
blitter.destroy();
}
void ext::vulkan::RenderTargetRenderMode::render() {
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
@ -529,44 +453,38 @@ void ext::vulkan::RenderTargetRenderMode::render() {
metadata.limiter.execute = false;
}
}
}
void ext::vulkan::RenderTargetRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
blitter.destroy();
}
if ( !metadata.limiter.execute ) return;
void ext::vulkan::RenderTargetRenderMode::render() {
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{} );
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, UINT64_MAX ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
// Pipeline stage at which the queue submission will wait (via pWaitSemaphores)
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
// The submit info structure specifices a command buffer queue submission batch
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
// submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed
// submitInfo.signalSemaphoreCount = 1; // One signal semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[states::currentBuffer]));
/*
VkSemaphoreWaitInfo waitInfo = {};
waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
waitInfo.flags = VK_SEMAPHORE_WAIT_ANY_BIT;
waitInfo.semaphoreCount = 1;
waitInfo.pSemaphores = &renderCompleteSemaphore;
waitInfo.pValues = NULL;
VK_CHECK_RESULT(vkWaitSemaphores( *device, &waitInfo, UINT64_MAX ));
*/
if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{} );
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };

View File

@ -44,7 +44,7 @@ void ext::vulkan::Swapchain::initialize( Device& device ) {
uf::stl::vector<VkPresentModeKHR> presentModes(presentModeCount);
VK_CHECK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(device.physicalDevice, device.surface, &presentModeCount, presentModes.data()));
#if 1
if ( settings::experimental::vsync ) {
if ( settings::pipelines::vsync ) {
swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
for ( size_t i = 0; i < presentModeCount; i++ ) {
if ( presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR ) {
@ -62,7 +62,7 @@ void ext::vulkan::Swapchain::initialize( Device& device ) {
}
}
#else
if ( !settings::experimental::vsync ) {
if ( !settings::pipelines::vsync ) {
for ( size_t i = 0; i < presentModeCount; i++ ) {
if ( presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR ) {
swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;

View File

@ -13,12 +13,17 @@
#include <fstream>
#include <atomic>
namespace {
uf::stl::vector<VkFence> auxFences;
}
uint32_t ext::vulkan::settings::width = 1280;
uint32_t ext::vulkan::settings::height = 720;
uint8_t ext::vulkan::settings::msaa = 1;
bool ext::vulkan::settings::validation = true;
// constexpr size_t ext::vulkan::settings::maxViews = 6;
size_t ext::vulkan::settings::viewCount = 2;
size_t ext::vulkan::settings::gpuID = -1;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::validationFilters;
uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedDeviceFeatures;
@ -27,21 +32,28 @@ uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedInstanceExtensi
VkFilter ext::vulkan::settings::swapchainUpscaleFilter = VK_FILTER_LINEAR;
// these go hand in hand for the above
bool ext::vulkan::settings::experimental::dedicatedThread = false;
bool ext::vulkan::settings::experimental::rebuildOnTickBegin = false;
bool ext::vulkan::settings::experimental::waitOnRenderEnd = false;
bool ext::vulkan::settings::experimental::individualPipelines = true;
bool ext::vulkan::settings::experimental::multithreadedCommandRecording = true;
bool ext::vulkan::settings::experimental::multithreadedCommandRendering = false;
uf::stl::string ext::vulkan::settings::experimental::deferredMode = "";
bool ext::vulkan::settings::experimental::deferredReconstructPosition = false;
bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true;
bool ext::vulkan::settings::experimental::multiview = true;
bool ext::vulkan::settings::experimental::vsync = true;
bool ext::vulkan::settings::experimental::hdr = true;
bool ext::vulkan::settings::experimental::vxgi = true;
bool ext::vulkan::settings::experimental::deferredSampling = true;
bool ext::vulkan::settings::experimental::culling = false;
bool ext::vulkan::settings::experimental::bloom = false;
bool ext::vulkan::settings::experimental::batchQueueSubmissions = false;
// not so experimental
bool ext::vulkan::settings::invariant::waitOnRenderEnd = false;
bool ext::vulkan::settings::invariant::individualPipelines = true;
bool ext::vulkan::settings::invariant::multithreadedRecording = true;
uf::stl::string ext::vulkan::settings::invariant::deferredMode = "";
bool ext::vulkan::settings::invariant::deferredReconstructPosition = false;
bool ext::vulkan::settings::invariant::deferredAliasOutputToSwapchain = true;
bool ext::vulkan::settings::invariant::deferredSampling = true;
bool ext::vulkan::settings::invariant::multiview = true;
// pipelines
bool ext::vulkan::settings::pipelines::vsync = true;
bool ext::vulkan::settings::pipelines::hdr = true;
bool ext::vulkan::settings::pipelines::vxgi = true;
bool ext::vulkan::settings::pipelines::culling = false;
bool ext::vulkan::settings::pipelines::bloom = false;
VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace;
ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM;
@ -57,9 +69,8 @@ std::mutex ext::vulkan::mutex;
bool ext::vulkan::states::resized = false;
bool ext::vulkan::states::rebuild = false;
uint32_t ext::vulkan::states::currentBuffer = 0;
uf::ThreadUnique<ext::vulkan::RenderMode*> ext::vulkan::currentRenderMode;
uf::stl::vector<uf::Scene*> ext::vulkan::scenes;
ext::vulkan::RenderMode* ext::vulkan::currentRenderMode = NULL;
uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::renderModes = {
new ext::vulkan::BaseRenderMode,
};
@ -146,8 +157,25 @@ bool ext::vulkan::hasRenderMode( const uf::stl::string& name, bool isName ) {
ext::vulkan::RenderMode& ext::vulkan::addRenderMode( ext::vulkan::RenderMode* mode, const uf::stl::string& name ) {
mode->metadata.name = name;
renderModesMap[name] = renderModes.emplace_back(mode);
VK_VALIDATION_MESSAGE("Adding RenderMode: " << name << ": " << mode->getType());
// reorder
if ( hasRenderMode("Gui", true) ) {
RenderMode& primary = getRenderMode("Gui", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
if ( hasRenderMode("", true) ) {
RenderMode& primary = getRenderMode("", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
} else {
RenderMode& primary = getRenderMode("Swapchain", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
ext::vulkan::states::rebuild = true;
return *mode;
}
@ -193,6 +221,21 @@ void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) {
if ( free ) delete mode;
ext::vulkan::states::rebuild = true;
}
ext::vulkan::RenderMode* UF_API ext::vulkan::getCurrentRenderMode() {
return getCurrentRenderMode( std::this_thread::get_id() );
}
ext::vulkan::RenderMode* UF_API ext::vulkan::getCurrentRenderMode( std::thread::id id ) {
// bool exists = ext::vulkan::currentRenderMode.has(id);
// auto& currentRenderMode = ext::vulkan::currentRenderMode.get(id);
// return currentRenderMode;
return ext::vulkan::currentRenderMode.get(id);
}
void UF_API ext::vulkan::setCurrentRenderMode( ext::vulkan::RenderMode* renderMode ) {
return setCurrentRenderMode( renderMode, std::this_thread::get_id() );
}
void UF_API ext::vulkan::setCurrentRenderMode( ext::vulkan::RenderMode* renderMode, std::thread::id id ) {
ext::vulkan::currentRenderMode.get(id) = renderMode;
}
void ext::vulkan::initialize() {
ext::vulkan::mutex.lock();
@ -252,6 +295,16 @@ void ext::vulkan::initialize() {
TextureCube::empty.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
TextureCube::empty.fromBuffers( (void*) &pixels[0], pixels.size(), ext::vulkan::enums::Format::R8G8B8A8_UNORM, 2, 2, 1, 6, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
}
{
::auxFences.resize( swapchain.buffers );
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
for ( auto& fence : ::auxFences ) VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
uf::graph::initialize();
@ -259,14 +312,18 @@ void ext::vulkan::initialize() {
if ( !renderMode ) continue;
renderMode->initialize(device);
}
pod::Thread::container_t jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( settings::experimental::individualPipelines ) renderMode->bindPipelines();
if ( settings::experimental::multithreadedCommandRecording ) jobs.emplace_back([&](){renderMode->createCommandBuffers();});
else renderMode->createCommandBuffers();
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
tasks.queue([&]{
renderMode->lockMutex();
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
renderMode->unlockMutex();
});
}
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
uf::thread::execute( tasks );
ext::vulkan::mutex.unlock();
}
void ext::vulkan::tick() {
@ -274,34 +331,78 @@ void ext::vulkan::tick() {
if ( ext::vulkan::states::resized || ext::vulkan::settings::experimental::rebuildOnTickBegin ) {
ext::vulkan::states::rebuild = true;
}
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
if ( graphic.initialized || !graphic.process || graphic.initialized ) continue;
graphic.initializePipeline();
ext::vulkan::states::rebuild = true;
#if 0
{
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
if ( graphic.initialized || !graphic.process || graphic.initialized ) continue;
tasks.queue([&]{
graphic.initializePipeline();
ext::vulkan::states::rebuild = true;
});
}
uf::thread::execute( tasks );
}
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( !renderMode->device ) {
renderMode->initialize(ext::vulkan::device);
#else
{
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
if ( graphic.initialized || !graphic.process || graphic.initialized ) continue;
graphic.initializePipeline();
ext::vulkan::states::rebuild = true;
}
renderMode->tick();
}
pod::Thread::container_t jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( ext::vulkan::states::rebuild || renderMode->rebuild ) {
if ( settings::experimental::individualPipelines ) renderMode->bindPipelines();
if ( settings::experimental::multithreadedCommandRecording ) jobs.emplace_back([&](){renderMode->createCommandBuffers();});
else renderMode->createCommandBuffers();
#endif
#if 0
{
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( !renderMode->device ) {
tasks.queue([&]{
renderMode->initialize(ext::vulkan::device);
ext::vulkan::states::rebuild = true;
renderMode->tick();
});
} else {
tasks.queue([&]{
renderMode->tick();
});
}
}
uf::thread::execute( tasks );
}
#else
{
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( !renderMode->device ) {
renderMode->initialize(ext::vulkan::device);
ext::vulkan::states::rebuild = true;
}
renderMode->tick();
}
}
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
#endif
{
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
if ( ext::vulkan::states::rebuild || renderMode->rebuild ) tasks.queue([&]{
renderMode->lockMutex();
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
renderMode->unlockMutex();
});
}
uf::thread::execute( tasks );
}
ext::vulkan::states::rebuild = false;
ext::vulkan::states::resized = false;
@ -309,66 +410,85 @@ void ext::vulkan::tick() {
}
void ext::vulkan::render() {
ext::vulkan::mutex.lock();
if ( hasRenderMode("Gui", true) ) {
RenderMode& primary = getRenderMode("Gui", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
if ( hasRenderMode("", true) ) {
RenderMode& primary = getRenderMode("", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
} else {
RenderMode& primary = getRenderMode("Swapchain", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
#if 1
pod::Thread::container_t jobs;
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute ) continue;
ext::vulkan::currentRenderMode = renderMode;
if ( settings::experimental::multithreadedCommandRendering ) {
jobs.emplace_back([&]{
if ( settings::experimental::batchQueueSubmissions ) {
uf::stl::vector<RenderMode*> auxRenderModes; auxRenderModes.reserve( renderModes.size() );
uf::stl::vector<RenderMode*> specialRenderModes; specialRenderModes.reserve( renderModes.size() );
for ( auto renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue;
renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
if ( renderMode->commandBufferCallbacks.count(RenderMode::EXECUTE_BEGIN) > 0 ) renderMode->commandBufferCallbacks[RenderMode::EXECUTE_BEGIN]( VkCommandBuffer{} );
if ( renderMode->getName() == "Gui" || renderMode->getName() == "" || renderMode->getName() == "Swapchain" )
specialRenderModes.emplace_back(renderMode);
else
auxRenderModes.emplace_back(renderMode);
}
// stuff we can batch
{
// Get next image in the swap chain (back/front buffer)
uf::stl::vector<VkSubmitInfo> submits; submits.reserve( auxRenderModes.size() );
for ( auto renderMode : auxRenderModes ) {
auto submitInfo = renderMode->queue();
if ( submitInfo.sType != VK_STRUCTURE_TYPE_SUBMIT_INFO ) continue;
ext::vulkan::setCurrentRenderMode(renderMode);
uf::graph::render();
uf::scene::render();
submits.emplace_back(submitInfo);
renderMode->executed = true;
ext::vulkan::setCurrentRenderMode(NULL);
}
if ( !submits.empty() ) {
VK_CHECK_RESULT(vkWaitForFences(device, 1, &::auxFences[states::currentBuffer], VK_TRUE, UINT64_MAX));
VK_CHECK_RESULT(vkResetFences(device, 1, &::auxFences[states::currentBuffer]));
VK_CHECK_RESULT(vkQueueSubmit(device.getQueue( Device::QueueEnum::GRAPHICS ), submits.size(), submits.data(), ::auxFences[states::currentBuffer]));
}
}
// stuff we can't batch
{
for ( auto renderMode : specialRenderModes ) {
ext::vulkan::setCurrentRenderMode(renderMode);
uf::graph::render();
uf::scene::render();
renderMode->render();
renderMode->executed = true;
});
} else {
ext::vulkan::setCurrentRenderMode(NULL);
}
}
for ( auto renderMode : renderModes ) {
if ( renderMode->commandBufferCallbacks.count(RenderMode::EXECUTE_END) > 0 ) renderMode->commandBufferCallbacks[RenderMode::EXECUTE_END]( VkCommandBuffer{} );
renderMode->unlockMutex( renderMode->mostRecentCommandPoolId );
}
} else {
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue;
renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
ext::vulkan::setCurrentRenderMode(renderMode);
uf::graph::render();
uf::scene::render();
renderMode->render();
renderMode->executed = true;
ext::vulkan::setCurrentRenderMode(NULL);
renderMode->unlockMutex( renderMode->mostRecentCommandPoolId );
}
}
if ( !jobs.empty() ) uf::thread::batchWorkers( jobs );
#else
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute ) continue;
ext::vulkan::currentRenderMode = renderMode;
uf::scene::render();
renderMode->render();
renderMode->executed = true;
}
#endif
ext::vulkan::currentRenderMode = NULL;
if ( ext::vulkan::settings::experimental::waitOnRenderEnd ) {
synchronize();
}
/*
if ( ext::openvr::context ) {
ext::openvr::postSubmit();
}
*/
if ( ext::vulkan::settings::invariant::waitOnRenderEnd ) synchronize();
// if ( ext::openvr::context ) ext::openvr::postSubmit();
ext::vulkan::mutex.unlock();
}
void ext::vulkan::destroy() {
ext::vulkan::mutex.lock();
synchronize();
for ( auto& fence : ::auxFences ) vkDestroyFence( device, fence, nullptr);
Texture2D::empty.destroy();
Texture3D::empty.destroy();
TextureCube::empty.destroy();

View File

@ -143,13 +143,16 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
packOptions.resolution = graph.metadata["baking"]["resolution"].as(packOptions.resolution);
// pack
pod::Thread::container_t jobs;
#if UF_XATLAS_UNWRAP_MULTITHREAD
auto tasks = uf::thread::schedule("Async");
#else
auto tasks = uf::thread::schedule("Main");
#endif
for ( auto& pair : atlases ) {
jobs.emplace_back([&]{
tasks.queue([&]{
auto& atlas = pair.second;
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
/*
#if !UF_XATLAS_LAZY
// get vertices size ahead of time
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
auto& xmesh = atlas.pointer->meshes[i];
@ -157,15 +160,10 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
// atlas.vertices += xmesh.vertexCount;
sizes[entry.index] += xmesh.vertexCount;
}
*/
#endif
});
}
#if UF_XATLAS_UNWRAP_MULTITHREAD
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
#else
for ( auto& job : jobs ) job();
#endif
uf::thread::execute( tasks );
#if !UF_XATLAS_LAZY
for ( auto& pair : atlases ) {

View File

@ -9,8 +9,7 @@ uint uf::thread::workers = 1;
std::thread::id uf::thread::mainThreadId = std::this_thread::get_id();
bool uf::thread::async = false;
#define UF_THREAD_ANNOUNCE(x)\
//uf::iostream << x << "\n";
#define UF_THREAD_ANNOUNCE(x) //UF_MSG_DEBUG(x)
void UF_API uf::thread::start( pod::Thread& thread ) { if ( thread.running ) return;
thread.thread = std::thread( uf::thread::tick, std::ref(thread) );
@ -34,7 +33,7 @@ void UF_API uf::thread::tick( pod::Thread& thread ) {
while ( thread.running ) {
uf::thread::process( thread );
if ( thread.terminates && thread.temps.empty() && thread.consts.empty() ) uf::thread::quit( thread );
if ( thread.terminates && thread.queue.empty() && thread.container.empty() ) uf::thread::quit( thread );
if ( thread.limiter > 0 ) {
long long sleep = (thread.limiter * 1000) - thread.timer.elapsed().asMilliseconds();
@ -55,13 +54,54 @@ pod::Thread& UF_API uf::thread::fetchWorker( const uf::stl::string& name ) {
if ( ++current >= limit ) current = 0;
uf::stl::string thread = name;
if ( current > 0 ) thread += " " + std::to_string(current);
bool exists = uf::thread::has(thread);
auto& pod = exists ? uf::thread::get(thread) : uf::thread::create(thread, true);
auto& pod = uf::thread::get(thread);
if ( std::this_thread::get_id() != pod.thread.get_id() ) return pod;
}
return uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create("Main", true);
return uf::thread::get("Main");
}
pod::Thread::Tasks UF_API uf::thread::schedule( const uf::stl::string& name, bool wait ) {
pod::Thread::Tasks tasks = {
.name = name,
.waits = wait,
};
return tasks;
}
void UF_API uf::thread::execute( pod::Thread::Tasks& tasks ) {
if ( tasks.container.empty() ) return;
if ( tasks.name == "Main" ) {
// for ( auto& task : tasks.container ) task();
while ( !tasks.container.empty() ) {
auto& task = tasks.container.front();
task();
tasks.container.pop();
}
} else if ( tasks.name == "Async" ) {
uf::stl::vector<std::future<void>> futures;
futures.reserve(tasks.container.size());
// for ( auto& task : tasks.container ) {
while ( !tasks.container.empty() ) {
auto task = tasks.container.front();
futures.emplace_back(std::async( std::launch::async, task ));
tasks.container.pop();
}
if ( tasks.waits ) for ( auto& future : futures ) future.wait();
} else {
uf::stl::vector<pod::Thread*> workers;
// for ( auto& task : tasks.container ) {
while ( !tasks.container.empty() ) {
auto task = tasks.container.front();
auto& worker = uf::thread::fetchWorker( tasks.name );
uf::thread::queue( worker, task );
workers.emplace_back(&worker);
tasks.container.pop();
}
if ( tasks.waits ) for ( auto& worker : workers ) uf::thread::wait( *worker );
}
}
/*
void UF_API uf::thread::batchWorker( const pod::Thread::function_t& function, const uf::stl::string& name ) {
return batchWorkers( { function }, false, name );
}
@ -70,7 +110,7 @@ void UF_API uf::thread::batchWorkers( const uf::stl::vector<pod::Thread::functio
for ( auto& function : functions ) {
auto& worker = uf::thread::fetchWorker( name );
workers.emplace_back(&worker);
uf::thread::add( worker, function, true );
uf::thread::queue( worker, function );
}
if ( wait ) for ( auto& worker : workers ) uf::thread::wait( *worker );
}
@ -82,14 +122,34 @@ void UF_API uf::thread::batchWorkers_Async( const uf::stl::vector<pod::Thread::f
if ( wait ) for ( auto& future : futures ) future.wait();
return;
}
void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t& function, bool temporary ) {
*/
/*
void UF_API uf::thread::add( pod::Thread& thread, bool queued, const pod::Thread::function_t& function ) {
if ( thread.mutex != NULL ) thread.mutex->lock();
temporary ? thread.temps.push( function ) : thread.consts.push_back( function );
queue ? thread.queue.push( function ) : thread.container.push_back( function );
if ( thread.mutex != NULL ) thread.mutex->unlock();
}
*/
void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t& function ) {
if ( thread.mutex != NULL ) thread.mutex->lock();
thread.container.emplace_back( function );
if ( thread.mutex != NULL ) thread.mutex->unlock();
}
void UF_API uf::thread::queue( const pod::Thread::container_t& functions ) {
for ( auto& function : functions )
uf::thread::queue( uf::thread::fetchWorker(), function );
}
void UF_API uf::thread::queue( const pod::Thread::function_t& function ) {
return uf::thread::queue( uf::thread::fetchWorker(), function );
}
void UF_API uf::thread::queue( pod::Thread& thread, const pod::Thread::function_t& function ) {
if ( thread.mutex != NULL ) thread.mutex->lock();
thread.queue.emplace( function );
if ( thread.mutex != NULL ) thread.mutex->unlock();
}
void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { UF_THREAD_ANNOUNCE("Bad Thread: " << thread.uid << " " << thread.name); return; } //ops
while ( !thread.temps.empty() ) {
auto& function = thread.temps.front();
while ( !thread.queue.empty() ) {
auto& function = thread.queue.front();
if ( function )
#if UF_EXCEPTIONS
try {
@ -100,9 +160,9 @@ void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(u
UF_MSG_ERROR("Thread " << thread.name << " (UID: " << thread.uid << ") caught exception: " << e.what());
}
#endif
thread.temps.pop();
thread.queue.pop();
}
for ( auto function : thread.consts ) {
for ( auto function : thread.container ) {
if ( function )
#if UF_EXCEPTIONS
try {
@ -119,10 +179,10 @@ void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(u
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();});
thread.condition.wait(lock, [&]{return thread.queue.empty();});
return;
}
while ( !thread.temps.empty() );
while ( !thread.queue.empty() );
}
const uf::stl::string& UF_API uf::thread::name( const pod::Thread& thread ) {
@ -142,6 +202,8 @@ void UF_API uf::thread::terminate() {
}
}
pod::Thread& UF_API uf::thread::create( const uf::stl::string& name, bool start, bool locks ) {
if ( name == "Main" ) start = false;
pod::Thread* pointer = NULL;
uf::thread::threads.emplace_back(pointer = new pod::Thread);
pod::Thread& thread = *pointer;
@ -154,11 +216,11 @@ pod::Thread& UF_API uf::thread::create( const uf::stl::string& name, bool start,
thread.terminates = false;
thread.running = false;
thread.mutex = NULL;
thread.mutex = locks ? new std::mutex() : NULL;
thread.mutex = locks ? new std::mutex : NULL;
thread.limiter = uf::thread::limiter;
thread.affinity = (thread.uid % limit) + 1;
UF_THREAD_ANNOUNCE("Creating Thread #" << thread.uid << " (" << name << ") " << &thread << " (Affinity: " << thread.affinity << ") (Limiter: " << (1.0f / thread.limiter) << " FPS)");
UF_THREAD_ANNOUNCE("Creating Thread #" << thread.uid << " (" << name << ") " << &thread << " (Affinity: " << thread.affinity << ") (Limiter: " << (1.0f / thread.limiter) << " FPS)" << (locks ? " with mutex" : ""));
if ( start ) uf::thread::start( thread );
@ -169,7 +231,6 @@ void UF_API uf::thread::destroy( pod::Thread& thread ) {
UF_THREAD_ANNOUNCE("Quitting Thread #" << thread.uid << " (" << thread.name << ")");
uf::thread::quit( thread );
UF_THREAD_ANNOUNCE("Quitted Thread #" << thread.uid << " (" << thread.name << ")");
if ( thread.mutex != NULL ) delete thread.mutex;
@ -193,6 +254,7 @@ pod::Thread& UF_API uf::thread::get( uint uid ) {
UF_EXCEPTION("Thread error: invalid call");
}
pod::Thread& UF_API uf::thread::get( const uf::stl::string& name ) {
if ( !uf::thread::has(name) ) return uf::thread::create(name);
for ( pod::Thread* thread : uf::thread::threads ) if ( uf::thread::name(*thread) == name ) return *thread;
UF_EXCEPTION("Thread error: invalid call");
}

View File

@ -54,7 +54,6 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
metadata.cull = metadataJson["baking"]["cull"].as<bool>();
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
renderMode.execute = false;
renderMode.metadata.type = "single";
@ -90,6 +89,9 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
shader.textures.emplace_back().aliasTexture( metadata.buffers.baked );
});
UF_MSG_DEBUG("Finished initialiation.");
uf::thread::queue([&]{
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
});
});
this->queueHook( "entity:PostInitialization.%UID%", ext::json::null(), 1 );
@ -124,10 +126,14 @@ SAVE: {
renderMode.execute = false;
UF_MSG_DEBUG("Baking...");
pod::Thread::container_t jobs;
for ( size_t i = 0; i < metadata.max.layers; ++i ) {
jobs.emplace_back([&, i]{
#if UF_BAKER_SAVE_MULTITHREAD
auto tasks = uf::thread::schedule("Async");
#else
auto tasks = uf::thread::schedule("Main");
#endif
// 0 is always broken, do not save it
for ( size_t i = 1; i < metadata.max.layers; ++i ) {
tasks.queue([&, i]{
// auto image = renderMode.screenshot(0, i);
auto image = metadata.buffers.baked.screenshot(i);
uf::stl::string filename = uf::string::replace( metadata.output, "%i", std::to_string(i) );
@ -135,11 +141,8 @@ SAVE: {
UF_MSG_DEBUG("Writing to " << filename << ": " << status);
});
}
#if UF_BAKER_SAVE_MULTITHREAD
if ( !jobs.empty() ) uf::thread::batchWorkers_Async( jobs );
#else
for ( auto& job : jobs ) job();
#endif
uf::thread::execute( tasks );
UF_MSG_DEBUG("Baked.");
metadata.initialized.map = true;

View File

@ -1,525 +0,0 @@
#include <uf/config.h>
#if UF_USE_OPENVR
#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/window/window.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/audio/audio.h>
#include <uf/ext/openvr/openvr.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/math/collision.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/renderer/renderer.h>
#include <sstream>
namespace {
struct {
uf::Object* left;
uf::Object* right;
} hands, lines, lights;
}
UF_BEHAVIOR_REGISTER_CPP(ext::PlayerHandBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::PlayerHandBehavior, ticks = true, renders = true, multithread = false)
#define this (&self)
void ext::PlayerHandBehavior::initialize( uf::Object& self ) {
#if UF_USE_OPENVR
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
{
::hands.left = (uf::Object*) &uf::instantiator::instantiate("Object");
::hands.right = (uf::Object*) &uf::instantiator::instantiate("Object");
::lines.left = (uf::Object*) &uf::instantiator::instantiate("Object");
::lines.right = (uf::Object*) &uf::instantiator::instantiate("Object");
this->addChild(::hands.left);
this->addChild(::hands.right);
::hands.left->addChild(::lines.left);
::hands.right->addChild(::lines.right);
}
{
bool loaded = true;
for ( auto it = metadata["hands"].begin(); it != metadata["hands"].end(); ++it ) {
uf::stl::string key = it.key();
if ( !ext::openvr::requestRenderModel(metadata["hands"][key]["controller"]["model"].as<uf::stl::string>()) ) loaded = false;
}
if ( !loaded ) {
this->addHook( "VR:Model.Loaded", [&](pod::payloads::assetLoad& payload){
uf::stl::string name = payload.filename; // json["name"].as<uf::stl::string>();
uf::stl::string side = "";
if ( name == metadata["hands"]["left"]["controller"]["model"].as<uf::stl::string>() ) {
side = "left";
} else if ( name == metadata["hands"]["right"]["controller"]["model"].as<uf::stl::string>() ) {
side = "right";
};
if ( side == "" ) return;
uf::Object& hand = *(side == "left" ? ::hands.left : ::hands.right);
uf::Object& line = *(side == "left" ? ::lines.left : ::lines.right);
{
uf::Graphic& graphic = (hand.getComponent<uf::Graphic>() = ext::openvr::getRenderModel( name ));
graphic.process = true;
graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW;
graphic.material.attachShader(uf::io::root+"/shaders/base/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root+"/shaders/base/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
uf::instantiator::bind( "EntityBehavior", hand );
uf::instantiator::bind( "ObjectBehavior", hand );
hand.initialize();
}
if ( metadata["hands"][side]["pointer"]["length"].as<float>() > 0 ) {
// line.addAlias<uf::LineMesh, uf::Mesh>();
pod::Transform<>& transform = line.getComponent<pod::Transform<>>();
transform.orientation = uf::quaternion::axisAngle(
{
metadata["hands"][side]["pointer"]["orientation"]["axis"][0].as<float>(),
metadata["hands"][side]["pointer"]["orientation"]["axis"][1].as<float>(),
metadata["hands"][side]["pointer"]["orientation"]["axis"][2].as<float>()
},
metadata["hands"][side]["pointer"]["orientation"]["angle"].as<float>() * 3.14159f / 180.0f
);
transform.position = {
metadata["hands"][side]["pointer"]["offset"][0].as<float>(),
metadata["hands"][side]["pointer"]["offset"][1].as<float>(),
metadata["hands"][side]["pointer"]["offset"][2].as<float>()
};
auto& mesh = line.getComponent<uf::LineMesh>();
auto& graphic = line.getComponent<uf::Graphic>();
mesh.vertices = {
{ {0.0f, 0.0f, 0.0f} },
{ {0.0f, 0.0f, metadata["hands"][side]["pointer"]["length"].as<float>()} },
};
graphic.initialize();
graphic.initializeMesh(mesh);
graphic.material.attachShader(uf::io::root+"/shaders/line/base.vert.spv", uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(uf::io::root+"/shaders/line/base.frag.spv", uf::renderer::enums::Shader::FRAGMENT);
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_STRIP;
graphic.descriptor.fill = uf::renderer::enums::PolygonMode::LINE;
graphic.descriptor.lineWidth = metadata["hands"][side]["pointer"]["width"].as<float>();
line.initialize();
}
if ( metadata["hands"][side]["light"]["should"].as<bool>() ){
auto& child = hand.loadChild("/light.json", false);
if (side == "left" )
lights.left = &child;
else
lights.right = &child;
auto& json = metadata["hands"][side]["light"];
auto& light = side == "left" ? *lights.left : *lights.right;
auto& metadata = light.getComponent<uf::Serializer>();
if ( !ext::json::isNull( json["color"] ) ) metadata["light"]["color"] = json["color"];
if ( !ext::json::isNull( json["radius"] ) ) metadata["light"]["radius"] = json["radius"];
if ( !ext::json::isNull( json["power"] ) ) metadata["light"]["power"] = json["power"];
if ( !ext::json::isNull( json["type"] ) ) metadata["light"]["type"] = json["type"];
if ( !ext::json::isNull( json["shadows"] ) ) metadata["light"]["shadows"] = json["shadows"];
metadata["lights"]["external update"] = true;
// light.initialize();
/*
auto* child = (uf::Object*) hand.findByUid(hand.loadChild("/light.json", false));
if ( child ) {
if (side == "left" ) lights.left = child; else lights.right = child;
auto& json = metadata["hands"][side]["light"];
auto& light = side == "left" ? *lights.left : *lights.right;
auto& metadata = light.getComponent<uf::Serializer>();
if ( !ext::json::isNull( json["color"] ) ) metadata["light"]["color"] = json["color"];
if ( !ext::json::isNull( json["radius"] ) ) metadata["light"]["radius"] = json["radius"];
if ( !ext::json::isNull( json["power"] ) ) metadata["light"]["power"] = json["power"];
if ( !ext::json::isNull( json["shadows"] ) ) metadata["light"]["shadows"] = json["shadows"];
metadata["lights"]["external update"] = true;
light.initialize();
}
*/
}
});
}
uf::stl::vector<uf::Object*> vHands = { ::hands.left, ::hands.right };
for ( auto pointer : vHands ) {
auto& hand = *pointer;
hand.addHook("VR:Input.Digital", [&]( pod::payloads::vrInputDigital& payload){
int_fast8_t side = &hand == hands.left ? -1 : 1;
if ( payload.side != side ) return;
// fire mouse click
if ( payload.name == "click" ) {
pod::payloads::windowMouseClick pload;
pload.type = "window:Mouse.Click";
pload.invoker = "vr";
pload.mouse.position = uf::vector::encode( metadata["hands"][side]["cursor"]["position"], pload.mouse.position );
pload.mouse.delta = {};
pload.mouse.button = side == -1 ? "Right" : "Left";
pload.mouse.state = payload.state;
uf::hooks.call( pload.type, payload );
}
});
hand.addHook("world:Collision.%UID%", [&]( pod::payloads::worldCollision& payload){
uf::stl::string side = &hand == hands.left ? "left" : "right";
pod::payloads::vrHaptics pload;
pload.delay = 0;
pload.duration = uf::physics::time::delta;
pload.frequency = 1;
pload.amplitude = fmin(1.0f, 1000.0f * payload.depth);
plaod.side = &hand == hands.left ? -1 : 1;;
uf::hooks.call( "VR:Haptics." + side, payload );
});
auto& transform = hand.getComponent<pod::Transform<>>();
auto& collider = hand.getComponent<uf::Collider>();
// auto* box = new uf::BoundingBox( transform.position, {0.25, 0.25, 0.25} );
// box->getTransform().reference = &transform;
// collider.add(box);
}
}
#endif
}
void ext::PlayerHandBehavior::tick( uf::Object& self ) {
#if UF_USE_OPENVR
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& controllerCamera = controller.getComponent<uf::Camera>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& controllerCameraTransform = controllerCamera.getTransform();
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
pod::Matrix4f playerModel = uf::matrix::identity(); {
auto& controller = this->getParent();
auto& camera = controller.getComponent<uf::Camera>();
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
pod::Matrix4f rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation );
playerModel = translation * rotation;
}
{
pod::Transform<>& transform = ::hands.left->getComponent<pod::Transform<>>();
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Left );
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Left );
transform.scale = { 1, 1, 1 };
transform.reference = &controllerTransform;
auto& collider = ::hands.left->getComponent<uf::Collider>();
for ( auto* box : collider.getContainer() ) {
box->getTransform().position = transform.position + controllerTransform.position + controllerCameraTransform.position;
}
}
{
pod::Transform<>& transform = ::hands.right->getComponent<pod::Transform<>>();
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Right );
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right );
transform.scale = { 1, 1, 1 };
transform.reference = &controllerTransform;
auto& collider = ::hands.right->getComponent<uf::Collider>();
for ( auto* box : collider.getContainer() ) {
box->getTransform().position = transform.position + controllerTransform.position + controllerCameraTransform.position;
}
}
{
pod::Transform<>& transform = ::lines.left->getComponent<pod::Transform<>>();
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Left, true );
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Left, true );
transform.scale = { 1, 1, 1 };
transform.reference = &controllerTransform;
if ( lights.left ) {
if ( lights.left->getUid() == 0 ) {
lights.left->initialize();
}
auto& light = *lights.left;
auto& lightTransform = light.getComponent<pod::Transform<>>();
lightTransform.position = controllerCameraTransform.position + controller.getComponent<pod::Transform<>>().position + transform.position;
auto& lightCamera = light.getComponent<uf::Camera>();
pod::Matrix4f playerModel = uf::matrix::identity();
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), controllerCameraTransform.position + controllerTransform.position );
pod::Matrix4f rotation = uf::quaternion::matrix( controllerTransform.orientation );
playerModel = translation * rotation;
pod::Matrix4f model = uf::matrix::inverse( playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true ) );
for ( size_t i = 0; i < 2; ++i ) lightCamera.setView( model, i );
}
}
{
pod::Transform<>& transform = ::lines.right->getComponent<pod::Transform<>>();
transform.position = ext::openvr::controllerPosition( vr::Controller_Hand::Hand_Right, true );
transform.orientation = ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right, true );
transform.scale = { 1, 1, 1 };
transform.reference = &controllerTransform;
if ( lights.right ) {
if ( lights.right->getUid() == 0 ) {
lights.right->initialize();
}
auto& light = *lights.right;
auto& lightTransform = light.getComponent<pod::Transform<>>();
lightTransform.position = controllerCameraTransform.position + controllerTransform.position + transform.position;
auto& lightCamera = light.getComponent<uf::Camera>();
pod::Matrix4f playerModel = uf::matrix::identity();
pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), controllerCameraTransform.position + controllerTransform.position );
pod::Matrix4f rotation = uf::quaternion::matrix( controllerTransform.orientation );
playerModel = translation * rotation;
pod::Matrix4f model = uf::matrix::inverse( playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true ) );
for ( size_t i = 0; i < 2; ++i ) lightCamera.setView( model, i );
}
}
//
if ( ::hands.left && ::hands.left->hasComponent<uf::Graphic>() ) {
auto& graphic = ::hands.left->getComponent<uf::Graphic>();
auto& transform = ::hands.left->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, false );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
};
auto& shader = graphic.material.getShader("vertex");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.model = model;
// uniforms.color = uf::vector::decode( metadata["hands"]["left"]["controller"]["color"], pod::Vector4f{1,1,1,1} );
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( renderMode.getName() == "" ) uniforms.model = pod::Matrix4f{};
} else uniforms.model = pod::Matrix4f{};
shader.updateUniform( "UBO", uniform );
}
}
if ( ::hands.right && ::hands.right->hasComponent<uf::Graphic>() ) {
auto& graphic = ::hands.right->getComponent<uf::Graphic>();
auto& transform = ::hands.right->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, false );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
};
auto& shader = graphic.material.getShader("vertex");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.model = model;
// uniforms.color = uf::vector::decode( metadata["hands"]["right"]["controller"]["color"], pod::Vector4f{1,1,1,1} );
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( renderMode.getName() == "" ) uniforms.model = pod::Matrix4f{};
} else uniforms.model = pod::Matrix4f{};
shader.updateUniform( "UBO", uniform );
}
}
if ( ::lines.left && ::lines.left->hasComponent<uf::Graphic>() ) {
auto& graphic = ::lines.left->getComponent<uf::Graphic>();
auto& transform = ::lines.left->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
};
auto& shader = graphic.material.getShader("vertex");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.model = model;
// uniforms.color = uf::vector::decode( metadata["hands"]["left"]["pointer"]["color"], pod::Vector4f{1,1,1,1} );
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( renderMode.getName() == "" ) uniforms.model = pod::Matrix4f{};
} else uniforms.model = pod::Matrix4f{};
shader.updateUniform( "UBO", uniform );
}
}
if ( ::lines.right && ::lines.right->hasComponent<uf::Graphic>() ) {
auto& graphic = ::lines.right->getComponent<uf::Graphic>();
auto& transform = ::lines.right->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
struct UniformDescriptor {
/*alignas(16)*/ pod::Matrix4f model;
};
auto& shader = graphic.material.getShader("vertex");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.model = model;
// uniforms.color = uf::vector::decode( metadata["hands"]["right"]["pointer"]["color"], pod::Vector4f{1,1,1,1} );
if ( uf::renderer::currentRenderMode ) {
auto& renderMode = *uf::renderer::currentRenderMode;
if ( renderMode.getName() == "" ) uniforms.model = pod::Matrix4f{};
} else uniforms.model = pod::Matrix4f{};
shader.updateUniform( "UBO", uniform );
}
}
// raytrace pointer / hand collision
{
uf::stl::vector<uf::Object*> handPointers = { ::hands.left, ::hands.right };
for ( auto pointer : handPointers ) { auto& hand = *pointer;
uf::stl::string side = &hand == ::hands.left ? "left" : "right";
if ( !ext::openvr::controllerActive( side == "left" ? vr::Controller_Hand::Hand_Left : vr::Controller_Hand::Hand_Right ) ) continue;
{
pod::Transform<>& transform = (side == "left" ? ::lines.left : ::lines.right)->getComponent<pod::Transform<>>();
struct {
pod::Vector3f origin;
pod::Vector3f direction;
} ray;
struct {
pod::Vector3f center;
pod::Vector3f normal;
} plane;
transform = uf::transform::reorient( transform );
ray.origin = transform.position;
ray.direction = transform.forward;
pod::Transform<> gtransform;
pod::Matrix4f mvp;
uf::Serializer& cMetadata = controller.getComponent<uf::Serializer>();
if ( ext::json::isArray( cMetadata["overlay"]["position"] ) )
gtransform.position = {
cMetadata["overlay"]["position"][0].as<float>(),
cMetadata["overlay"]["position"][1].as<float>(),
cMetadata["overlay"]["position"][2].as<float>(),
};
if ( ext::json::isArray( cMetadata["overlay"]["scale"] ) )
gtransform.scale = {
cMetadata["overlay"]["scale"][0].as<float>(),
cMetadata["overlay"]["scale"][1].as<float>(),
cMetadata["overlay"]["scale"][2].as<float>(),
};
if ( ext::json::isArray( cMetadata["overlay"]["orientation"] ) )
gtransform.orientation = {
cMetadata["overlay"]["orientation"][0].as<float>(),
cMetadata["overlay"]["orientation"][1].as<float>(),
cMetadata["overlay"]["orientation"][2].as<float>(),
cMetadata["overlay"]["orientation"][3].as<float>(),
};
plane.center = gtransform.position;
{
auto rotated = uf::quaternion::multiply( gtransform.orientation, pod::Vector4f{ 0, 0, 1, 1 } );
plane.normal.x = rotated.x;
plane.normal.y = rotated.y;
plane.normal.z = rotated.z;
plane.normal = uf::vector::normalize( plane.normal );
}
float denom = uf::vector::dot(plane.normal, ray.direction);
if (abs(denom) > 0.0001f) {
float t = uf::vector::dot( uf::vector::subtract(plane.center, ray.origin), plane.normal ) / denom;
if ( t >= 0 ) {
pod::Vector3f hit = ray.origin + (ray.direction * t);
pod::Vector3f translated = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity(), gtransform.scale ) ), uf::vector::subtract( plane.center, hit ) );
{
auto& metadata = this->getComponent<uf::Serializer>();
cMetadata["overlay"]["cursor"]["type"] = "vr";
cMetadata["overlay"]["cursor"]["position"][0] = translated.x;
cMetadata["overlay"]["cursor"]["position"][1] = translated.y;
cMetadata["overlay"]["cursor"]["position"][2] = translated.z;
metadata["hands"][side]["cursor"] = cMetadata["overlay"]["cursor"];
}
}
}
}
}
}
#endif
}
void ext::PlayerHandBehavior::render( uf::Object& self ){
#if UF_USE_OPENVR
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
if ( ::hands.left && ::hands.left->hasComponent<uf::Graphic>() ) {
auto& graphic = ::hands.left->getComponent<uf::Graphic>();
auto& transform = ::hands.left->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, false );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& uniform = shader.getUniform("Camera");
auto& uniforms = uniform.get<pod::Camera::Viewports>();
uniforms = camera.data().viewport;
shader.updateUniform("Camera", uniform);
}
}
if ( ::hands.right && ::hands.right->hasComponent<uf::Graphic>() ) {
auto& graphic = ::hands.right->getComponent<uf::Graphic>();
auto& transform = ::hands.right->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, false );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& uniform = shader.getUniform("Camera");
auto& uniforms = uniform.get<pod::Camera::Viewports>();
uniforms = camera.data().viewport;
shader.updateUniform("Camera", uniform);
}
}
if ( ::lines.left && ::lines.left->hasComponent<uf::Graphic>() ) {
auto& graphic = ::lines.left->getComponent<uf::Graphic>();
auto& transform = ::lines.left->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Left );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Left, true );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& uniform = shader.getUniform("Camera");
auto& uniforms = uniform.get<pod::Camera::Viewports>();
uniforms = camera.data().viewport;
shader.updateUniform("Camera", uniform);
}
}
if ( ::lines.right && ::lines.right->hasComponent<uf::Graphic>() ) {
auto& graphic = ::lines.right->getComponent<uf::Graphic>();
auto& transform = ::lines.right->getComponent<pod::Transform<>>();
graphic.process = ext::openvr::controllerActive( vr::Controller_Hand::Hand_Right );
pod::Matrix4f model = playerModel * ext::openvr::controllerModelMatrix( vr::Controller_Hand::Hand_Right, true );
if ( graphic.initialized && graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& uniform = shader.getUniform("Camera");
auto& uniforms = uniform.get<pod::Camera::Viewports>();
uniforms = camera.data().viewport;
shader.updateUniform("Camera", uniform);
}
}
#endif
}
void ext::PlayerHandBehavior::destroy( uf::Object& self ){}
void ext::PlayerHandBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {}
void ext::PlayerHandBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {}
#undef this
#endif

View File

@ -1,17 +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 {
namespace PlayerHandBehavior {
UF_BEHAVIOR_DEFINE_TYPE();
EXT_BEHAVIOR_DEFINE_TRAITS();
EXT_BEHAVIOR_DEFINE_FUNCTIONS();
UF_BEHAVIOR_DEFINE_METADATA(
);
}
}

View File

@ -65,7 +65,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
renderMode.metadata.type = "depth";
renderMode.metadata.pipeline = "depth";
if ( uf::renderer::settings::experimental::culling ) {
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back("culling");
}
renderMode.metadata.json["descriptor"]["depth bias"] = metadataJson["light"]["bias"];
@ -93,10 +93,10 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
camera.update(true);
uf::stl::string name = "RT:" + std::to_string((int) this->getUid());
uf::renderer::addRenderMode( &renderMode, name );
renderMode.blitter.process = false;
renderMode.width = size.x;
renderMode.height = size.y;
uf::renderer::addRenderMode( &renderMode, name );
}
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
@ -173,36 +173,43 @@ void ext::LightBehavior::tick( uf::Object& self ) {
}
#endif
// limit updating our shadow map
#if UF_USE_VULKAN
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
// enable renderer every X seconds
if ( metadata.renderer.limiter > 0 ) {
if ( metadata.renderer.timer > metadata.renderer.limiter ) {
metadata.renderer.timer = 0;
renderMode.execute = true;
renderMode.metadata.limiter.execute = true;
} else {
metadata.renderer.timer = metadata.renderer.timer + uf::physics::time::delta;
renderMode.execute = false;
renderMode.metadata.limiter.execute = false;
}
} else {
// round robin, enable if it's the light's current turn
if ( metadata.renderer.mode == "round robin" ) {
if ( ::roundRobin.current < ::roundRobin.lights.size() )
if ( ::roundRobin.current < ::roundRobin.lights.size() ) {
renderMode.execute = ::roundRobin.lights[::roundRobin.current] == this;
renderMode.metadata.limiter.execute = ::roundRobin.lights[::roundRobin.current] == this;
}
// render only if the light is used
} else if ( metadata.renderer.mode == "occlusion" ) {
renderMode.execute = metadata.renderer.rendered;
renderMode.metadata.limiter.execute = metadata.renderer.rendered;
// light baking, but sadly re-bakes every time the command buffer is recorded
} else if ( metadata.renderer.mode == "once" ) {
renderMode.execute = !metadata.renderer.rendered;
renderMode.metadata.limiter.execute = !metadata.renderer.rendered;
metadata.renderer.rendered = true;
} else if ( metadata.renderer.mode == "in-range" ) {
metadata.renderer.rendered = false;
}
}
// skip if we're handling the camera view matrix position ourselves
if ( renderMode.execute && !metadata.renderer.external ) {
if ( /*renderMode.execute*/ renderMode.metadata.limiter.execute && !metadata.renderer.external ) {
auto& camera = this->getComponent<uf::Camera>();
// omni light
if ( metadata.shadows && std::abs(metadata.type) == 1 ) {
@ -217,6 +224,7 @@ void ext::LightBehavior::tick( uf::Object& self ) {
}
}
}
#endif
#if UF_ENTITY_METADATA_USE_JSON
metadata.serialize(self, metadataJson);
#endif

View File

@ -71,6 +71,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
// sloppy
metadata.mouse.sensitivity = uf::vector::decode( ext::config["window"]["cursor"]["sensitivity"], metadata.mouse.sensitivity );
metadata.mouse.smoothing = uf::vector::decode( ext::config["window"]["cursor"]["smoothing"], metadata.mouse.smoothing );
this->addHook( "window:Mouse.CursorVisibility", [&](pod::payloads::windowMouseCursorVisibility& payload){
metadata.system.control = !payload.mouse.visible;
@ -78,28 +79,39 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
// Rotate Camera
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload ){
pod::Vector2 relta = { (float) metadata.mouse.sensitivity.x * payload.mouse.delta.x / payload.window.size.x, (float) metadata.mouse.sensitivity.y * payload.mouse.delta.y / payload.window.size.y };
// pod::Vector2 relta = { (float) metadata.mouse.sensitivity.x * payload.mouse.delta.x * uf::physics::time::delta, (float) metadata.mouse.sensitivity.y * payload.mouse.delta.y * uf::physics::time::delta };
const pod::Vector2ui deadZone{6, 6};
pod::Vector2f delta = {
(float) metadata.mouse.sensitivity.x * (abs(payload.mouse.delta.x) < deadZone.x ? 0 : payload.mouse.delta.x) / payload.window.size.x,
(float) metadata.mouse.sensitivity.y * (abs(payload.mouse.delta.y) < deadZone.y ? 0 : payload.mouse.delta.y) / payload.window.size.y
};
// pod::Vector2f delta = metadata.mouse.sensitivity * payload.mouse.delta / payload.window.size;
if ( (payload.mouse.delta.x == 0 && payload.mouse.delta.y == 0) || !metadata.system.control ) return;
// relta *= uf::physics::time::delta;
if ( payload.mouse.delta.x != 0 ) {
metadata.camera.queued += delta;
// UF_MSG_DEBUG( "Window size: " << uf::vector::toString( payload.window.size ));
// UF_MSG_DEBUG( "Delta: " << uf::vector::toString( payload.mouse.delta ));
// UF_MSG_DEBUG( "Sensitivity: " << uf::vector::toString( metadata.mouse.sensitivity ) );
/*
if ( relta.x != 0 ) {
if ( metadata.camera.invert.x ) relta.x *= -1;
metadata.camera.limit.current.x += relta.x;
if ( metadata.camera.limit.current.x != metadata.camera.limit.current.x || ( metadata.camera.limit.current.x < metadata.camera.limit.max.x && metadata.camera.limit.current.x > metadata.camera.limit.min.x ) ) {
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, relta.x ); else
uf::transform::rotate( transform, transform.up, relta.x );
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, relta.x ); else
uf::transform::rotate( transform, transform.up, relta.x );
} else metadata.camera.limit.current.x -= relta.x;
}
if ( payload.mouse.delta.y != 0 ) {
if ( relta.y != 0 ) {
if ( metadata.camera.invert.y ) relta.y *= -1;
metadata.camera.limit.current.y += relta.y;
if ( metadata.camera.limit.current.y != metadata.camera.limit.current.y || ( metadata.camera.limit.current.y < metadata.camera.limit.max.y && metadata.camera.limit.current.y > metadata.camera.limit.min.y ) ) {
// if ( collider.body && !collider.shared ) uf::physics::impl::applyRotation( collider, cameraTransform.right, relta.y ); else
if ( metadata.camera.limit.current.y != metadata.camera.limit.current.y || ( metadata.camera.limit.current.y < metadata.camera.limit.max.y && metadata.camera.limit.current.y > metadata.camera.limit.min.y ) ) {
// if ( collider.body && !collider.shared ) uf::physics::impl::applyRotation( collider, cameraTransform.right, relta.y ); else
uf::transform::rotate( cameraTransform, cameraTransform.right, relta.y );
} else metadata.camera.limit.current.y -= relta.y;
}
camera.update(true);
*/
});
#if UF_USE_DISCORD
@ -369,7 +381,28 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
metadata.system.crouching = false;
}
if ( keys.lookRight ^ keys.lookLeft ) {
if ( metadata.camera.queued.x != 0 || metadata.camera.queued.y != 0 ) {
auto lookDelta = metadata.camera.queued;
if ( abs(lookDelta.x) > uf::physics::time::delta / metadata.mouse.smoothing.x ) lookDelta.x *= uf::physics::time::delta * metadata.mouse.smoothing.x;
if ( abs(lookDelta.y) > uf::physics::time::delta / metadata.mouse.smoothing.y ) lookDelta.y *= uf::physics::time::delta * metadata.mouse.smoothing.y;
metadata.camera.queued -= lookDelta;
if ( lookDelta.x != 0 ) {
if ( metadata.camera.invert.x ) lookDelta.x *= -1;
metadata.camera.limit.current.x += lookDelta.x;
if ( metadata.camera.limit.current.x != metadata.camera.limit.current.x || ( metadata.camera.limit.current.x < metadata.camera.limit.max.x && metadata.camera.limit.current.x > metadata.camera.limit.min.x ) ) {
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, lookDelta.x ); else
uf::transform::rotate( transform, transform.up, lookDelta.x );
} else metadata.camera.limit.current.x -= lookDelta.x;
}
if ( lookDelta.y != 0 ) {
if ( metadata.camera.invert.y ) lookDelta.y *= -1;
metadata.camera.limit.current.y += lookDelta.y;
if ( metadata.camera.limit.current.y != metadata.camera.limit.current.y || ( metadata.camera.limit.current.y < metadata.camera.limit.max.y && metadata.camera.limit.current.y > metadata.camera.limit.min.y ) ) {
// if ( collider.body && !collider.shared ) uf::physics::impl::applyRotation( collider, cameraTransform.right, lookDelta.y ); else
uf::transform::rotate( cameraTransform, cameraTransform.right, lookDelta.y );
} else metadata.camera.limit.current.y -= lookDelta.y;
}
} else if ( keys.lookRight ^ keys.lookLeft ) {
if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else
uf::transform::rotate( transform, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) );
}

View File

@ -35,9 +35,11 @@ namespace ext {
pod::Vector3f max = {NAN, NAN, NAN};
} limit;
pod::Vector3t<bool> invert;
pod::Vector2f queued;
} camera;
struct {
pod::Vector2f sensitivity;
pod::Vector2f sensitivity = {1,1};
pod::Vector2f smoothing = {10,10};
} mouse;
struct {
struct {

View File

@ -226,6 +226,12 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
}
}
}
/* Mark as ready for multithreading */ {
TIMER(1, uf::inputs::kbm::states::M && ) {
uf::renderer::settings::experimental::dedicatedThread = !uf::renderer::settings::experimental::dedicatedThread;
UF_MSG_DEBUG("Toggling multithreaded rendering...");
}
}
#endif
#if 0
/* Print World Tree */ {
@ -416,7 +422,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
bool hasRT = entity->hasComponent<uf::renderer::RenderTargetRenderMode>();
if ( hasRT ) {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
if ( metadata.renderer.mode == "in-range" ) renderMode.execute = false;
if ( metadata.renderer.mode == "in-range" ) {
renderMode.execute = false;
renderMode.metadata.limiter.execute = false;
}
}
if ( metadata.power <= 0 ) continue;
auto flatten = uf::transform::flatten( entity->getComponent<pod::Transform<>>() );
@ -468,7 +477,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
auto& lightMetadata = entity->getComponent<ext::LightBehavior::Metadata>();
lightMetadata.renderer.rendered = true;
// activate our shadow mapper if it's range-basedd
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) renderMode.execute = true;
if ( lightMetadata.renderer.mode == "in-range" && shadowUpdateThreshold-- > 0 ) {
renderMode.execute = true;
renderMode.metadata.limiter.execute = true;
}
// if point light, and combining is requested
if ( metadata.shadow.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) {
int32_t index = -1;
@ -531,7 +543,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
uf::graph::storage.buffers.light.update( (const void*) uf::graph::storage.lights.data(), uf::graph::storage.lights.size() * sizeof(pod::Light) );
}
#endif
/* Update lights */ if ( !uf::renderer::settings::experimental::vxgi ) {
/* Update lights */ if ( !uf::renderer::settings::pipelines::vxgi ) {
ext::ExtSceneBehavior::bindBuffers( *this );
}
}
@ -638,7 +650,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
}
#endif
if ( uf::renderer::settings::experimental::bloom ) {
if ( uf::renderer::settings::pipelines::bloom ) {
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitters().front();
auto& shader = blitter.material.getShader("compute", "bloom");
@ -778,7 +790,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
textures3D.emplace_back().aliasTexture(sceneTextures.noise);
// attach VXGI voxels
if ( uf::renderer::settings::experimental::vxgi ) {
if ( uf::renderer::settings::pipelines::vxgi ) {
for ( auto& t : sceneTextures.voxels.id ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) textures3D.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) textures3D.emplace_back().aliasTexture(t);

View File

@ -110,7 +110,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
renderMode.metadata.type = "vxgi";
renderMode.metadata.pipeline = "vxgi";
renderMode.metadata.pipelines.emplace_back("vxgi");
if ( uf::renderer::settings::experimental::culling ) {
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back("culling");
}
renderMode.metadata.samples = 1;
@ -126,7 +126,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
if ( renderMode.metadata.samples > 1 ) {
computeShaderFilename = uf::string::replace( computeShaderFilename, "frag", "msaa.frag" );
}
if ( uf::renderer::settings::experimental::deferredSampling ) {
if ( uf::renderer::settings::invariant::deferredSampling ) {
computeShaderFilename = uf::string::replace( computeShaderFilename, "frag", "deferredSampling.frag" );
}
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
@ -253,6 +253,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
}
} );
#endif
#if 0
auto& deferredRenderMode = uf::renderer::getRenderMode("", true);
deferredRenderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer ){
VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
@ -330,6 +331,7 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
);
}
});
#endif
}
#endif
}

View File

@ -33,6 +33,8 @@
#include <locale>
#include <codecvt>
#define EXT_COLOR_FLOATS 1
namespace {
#if UF_USE_FREETYPE
struct {
@ -40,7 +42,6 @@ namespace {
uf::stl::unordered_map<uf::stl::string, uf::stl::unordered_map<uf::stl::string, uf::Glyph>> cache;
} glyphs;
#endif
uf::stl::string defaultRenderMode = "Gui";
uf::Serializer defaultSettings;
@ -65,7 +66,26 @@ namespace {
"clickable",
"hoverable"
};
struct /*UF_API*/ GuiMesh {
pod::Vector3f position;
pod::Vector2f uv;
#if EXT_COLOR_FLOATS
pod::Vector4f color;
#else
pod::ColorRgba color;
#endif
static uf::stl::vector<uf::renderer::AttributeDescriptor> descriptor;
};
}
UF_VERTEX_DESCRIPTOR(GuiMesh,
UF_VERTEX_DESCRIPTION(GuiMesh, R32G32B32_SFLOAT, position)
UF_VERTEX_DESCRIPTION(GuiMesh, R32G32_SFLOAT, uv)
UF_VERTEX_DESCRIPTION(GuiMesh, R8G8B8A8_UNORM, color)
)
uf::stl::vector<pod::GlyphBox> ext::Gui::generateGlyphs( const uf::stl::string& _string ) {
uf::stl::vector<pod::GlyphBox> gs;
#if UF_USE_FREETYPE
@ -324,16 +344,28 @@ void ext::Gui::load( const uf::Image& image ) {
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( image );
// auto& mesh = this->getComponent<ext::Gui::mesh_t>();
auto& transform = this->getComponent<pod::Transform<>>();
uf::stl::vector<pod::Vertex_3F2F3F> vertices = {
{ pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, metadata.color },
{ pod::Vector3f{-1.0f, -1.0f, 0.0f}, pod::Vector2f{0.0f, 0.0f}, metadata.color },
{ pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, metadata.color },
#if 0
uf::stl::vector<::GuiMesh> vertices = {
#else
auto& vertices = this->getComponent<uf::stl::vector<::GuiMesh>>();
#if EXT_COLOR_FLOATS
auto& color = metadata.color;
#else
pod::ColorRgba color = { metadata.color[0] * 255, metadata.color[1] * 255, metadata.color[2] * 255, metadata.color[3] * 255 };
#endif
vertices = {
#endif
{ pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, color },
{ pod::Vector3f{-1.0f, -1.0f, 0.0f}, pod::Vector2f{0.0f, 0.0f}, color },
{ pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, color },
{ pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, metadata.color },
{ pod::Vector3f{ 1.0f, 1.0f, 0.0f}, pod::Vector2f{1.0f, 1.0f}, metadata.color },
{ pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, metadata.color },
{ pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, color },
{ pod::Vector3f{ 1.0f, 1.0f, 0.0f}, pod::Vector2f{1.0f, 1.0f}, color },
{ pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, color },
};
uf::stl::vector<size_t> indices = {
0, 1, 2, 3, 4, 5
};
pod::Vector2f raidou = { 1, 1 };
@ -350,16 +382,23 @@ void ext::Gui::load( const uf::Image& image ) {
}
if ( metadataJson["world"].as<bool>() ) {
// metadataJson["gui layer"] = false;
} else {
#if UF_USE_OPENGL
if ( ext::json::isNull(metadataJson["cull mode"]) ) metadataJson["cull mode"] = "front";
#else
if ( uf::matrix::reverseInfiniteProjection ) {
// metadata.depth = -metadata.depth;
} else {
}
if ( metadataJson["flip uv"].as<bool>() ) for ( auto& v : vertices ) v.uv.y = 1 - v.uv.y;
#endif
if ( metadata.depth != 0.0f ) for ( auto& v : vertices ) v.position.z = metadata.depth;
else for ( auto& v : vertices ) v.position.z = 0;
}
graphic.descriptor.parse( metadataJson );
if ( uf::matrix::reverseInfiniteProjection ) {
} else {
metadata.depth = -metadata.depth;
}
if ( metadataJson["flip uv"].as<bool>() ) for ( auto& v : vertices ) v.uv.y = 1 - v.uv.y;
if ( metadata.depth != 0.0f ) for ( auto& v : vertices ) v.position.z = metadata.depth;
if ( metadataJson["scaling"].is<uf::stl::string>() ) {
uf::stl::string mode = metadataJson["scaling"].as<uf::stl::string>();
@ -376,6 +415,7 @@ void ext::Gui::load( const uf::Image& image ) {
transform.scale.x = raidou.x;
transform.scale.y = raidou.y;
}
#if 1
if ( metadataJson["layer"].is<uf::stl::string>() ) {
graphic.initialize( metadataJson["layer"].as<uf::stl::string>() );
} else if ( !ext::json::isNull( metadataJson["gui layer"] ) && !metadataJson["gui layer"].as<bool>() ) {
@ -385,11 +425,13 @@ void ext::Gui::load( const uf::Image& image ) {
} else {
graphic.initialize( ::defaultRenderMode );
}
#endif
// graphic.initialize();
auto& mesh = this->getComponent<uf::Mesh>();
mesh.bind<pod::Vertex_3F2F3F>();
mesh.bind<::GuiMesh>();
mesh.insertVertices( vertices );
// mesh.insertIndices( indices );
graphic.initializeMesh( mesh );
struct {
@ -653,21 +695,31 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
auto& transform = this->getComponent<pod::Transform<>>();
transform.scale.x = scale;
transform.scale.y = scale;
uf::stl::vector<pod::Vertex_3F2F3F> vertices;
#if 0
uf::stl::vector<::GuiMesh> vertices;
#else
auto& vertices = this->getComponent<uf::stl::vector<::GuiMesh>>();
#endif
uf::stl::vector<size_t> indices;
vertices.reserve( glyphs.size() * 6 );
indices.reserve( glyphs.size() * 6 );
for ( auto& g : glyphs ) {
auto glyphKey = std::to_string((uint64_t) g.code) + ";"+key;
auto& glyph = ::glyphs.cache[font][glyphKey];
auto hash = glyphHashMap[glyphKey];
#if EXT_COLOR_FLOATS
auto& color = g.color;
#else
pod::ColorRgba color = { g.color[0] * 255, g.color[1] * 255, g.color[2] * 255, g.color[3] * 255 };
#endif
// add vertices
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), g.color});
vertices.emplace_back(pod::Vertex_3F2F3F{pod::Vector3f{ g.box.x + g.box.w, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 0.0f }, hash ), g.color});
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), color}); indices.emplace_back( indices.size() );
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 1.0f }, hash ), color}); indices.emplace_back( indices.size() );
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), color}); indices.emplace_back( indices.size() );
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 0.0f, 0.0f }, hash ), color}); indices.emplace_back( indices.size() );
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x + g.box.w, g.box.y , 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 1.0f }, hash ), color}); indices.emplace_back( indices.size() );
vertices.emplace_back(::GuiMesh{pod::Vector3f{ g.box.x + g.box.w, g.box.y + g.box.h, 0 }, atlas.mapUv( pod::Vector2f{ 1.0f, 0.0f }, hash ), color}); indices.emplace_back( indices.size() );
}
for ( size_t i = 0; i < vertices.size(); i += 6 ) {
for ( size_t j = 0; j < 6; ++j ) {
@ -677,8 +729,9 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
vertex.position.z = metadata.depth;
}
}
mesh.bind<pod::Vertex_3F2F3F>();
mesh.bind<::GuiMesh>();
mesh.insertVertices( vertices );
// mesh.insertIndices( indices );
auto& texture = graphic.material.textures.emplace_back();
texture.loadFromImage( atlas.getAtlas() );
@ -746,17 +799,20 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
auto& graphic = this->getComponent<uf::Graphic>();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
auto& transform = this->getComponent<pod::Transform<>>();
auto transform = this->getComponent<pod::Transform<>>();
if ( !graphic.initialized ) return;
bool isGlyph = this->hasComponent<ext::GuiBehavior::GlyphMetadata>();
#if UF_USE_OPENGL
auto model = transform.model;
if ( metadata.mode == 0 ) {
transform.position.y = -transform.position.y;
}
auto model = uf::transform::model( transform );
auto& shader = graphic.material.getShader("vertex");
pod::Uniform uniform;
if ( metadata.mode == 1 ) {
uniform.modelView = transform.model;
uniform.modelView = model;
uniform.projection = uf::matrix::identity();
} else if ( metadata.mode == 2 ) {
auto& scene = uf::scene::getCurrentScene();
@ -784,6 +840,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
shader.updateUniform( "UBO", (const void*) &uniform, sizeof(uniform) );
pod::Uniform* uniformBuffer = (pod::Uniform*) shader.device->getBuffer(shader.getUniformBuffer("UBO").descriptor.buffer);
#if 0
UF_MSG_DEBUG( "buffer: " << uniformBuffer );
UF_MSG_DEBUG( "modelView: " << &uniformBuffer->modelView << " " << uf::matrix::toString( uniformBuffer->modelView ) );
@ -949,7 +1006,91 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
metadata.box.max.y = max.y;
}
}
void ext::GuiBehavior::render( uf::Object& self ){}
void ext::GuiBehavior::render( uf::Object& self ){
#if 0 && UF_USE_OPENGL
if ( !this->hasComponent<uf::Graphic>() ) return;
if ( ext::opengl::currentRenderMode->getName() != "Gui" ) return;
auto& metadata = this->getComponent<ext::GuiBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
auto& scene = uf::scene::getCurrentScene();
auto& graphic = this->getComponent<uf::Graphic>();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
auto& transform = this->getComponent<pod::Transform<>>();
if ( !graphic.initialized ) return;
auto& shader = graphic.material.getShader("vertex");
auto& mesh = this->getComponent<uf::Mesh>();
bool isGlyph = this->hasComponent<ext::GuiBehavior::GlyphMetadata>();
auto model = transform.model;
auto projection = uf::matrix::identity();
pod::Uniform uniform;
if ( metadata.mode == 1 ) {
uniform.modelView = transform.model;
uniform.projection = uf::matrix::identity();
} else if ( metadata.mode == 2 ) {
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
uniform.modelView = camera.getView() * uf::transform::model( transform );
uniform.projection = camera.getProjection();
} else if ( metadata.mode == 3 ) {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniform.modelView =
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
uniform.projection = camera.getProjection();
} else {
pod::Transform<> flatten = uf::transform::flatten( transform );
uniform.modelView =
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
uf::quaternion::matrix( flatten.orientation ) *
flatten.model;
uniform.projection = uf::matrix::identity();
}
GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW));
GL_ERROR_CHECK(glLoadMatrixf( &mat[0] ));
GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION));
GL_ERROR_CHECK(glLoadMatrixf( &mat[0] ));
if ( !graphic.material.textures.empty() ) {
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glEnable(GL_TEXTURE_2D));
GL_ERROR_CHECK(glBindTexture(GL_TEXTURE_2D, graphic.material.textures.front().descriptor));
}
glBegin(GL_TRIANGLES);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 0.5f,-0.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 0.5f,-0.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-0.5f,-0.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glEnd();
if ( !graphic.material.textures.empty() ) {
GL_ERROR_CHECK(glClientActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glActiveTexture(GL_TEXTURE0));
GL_ERROR_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
GL_ERROR_CHECK(glDisable(GL_TEXTURE_2D));
}
#endif
}
void ext::GuiBehavior::destroy( uf::Object& self ){}
void ext::GuiBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ){
serializer["gui"]["color"] = uf::vector::encode( color );

View File

@ -92,6 +92,8 @@ namespace {
} limiter, fps;
} engine;
} config;
bool requestDedicatedRenderThread = false;
}
void EXT_API ext::load() {
@ -265,12 +267,12 @@ void EXT_API ext::initialize() {
// Set worker threads
if ( configEngineThreadJson["workers"].as<uf::stl::string>() == "async" ) {
uf::thread::async = true;
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 ) / 2;
configEngineThreadJson["workers"] = threads;
uf::thread::workers = configEngineThreadJson["workers"].as<size_t>();
UF_MSG_DEBUG("Using async worker threads");
} else if ( configEngineThreadJson["workers"].as<uf::stl::string>() == "auto" ) {
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 ) / 2;
configEngineThreadJson["workers"] = threads;
uf::thread::workers = configEngineThreadJson["workers"].as<size_t>();
UF_MSG_DEBUG("Using " << threads << " worker threads");
@ -346,7 +348,9 @@ void EXT_API ext::initialize() {
#else
auto& configRenderJson = ::json["engine"]["ext"]["software"];
#endif
auto& configRenderInvariantJson = configRenderJson["invariant"];
auto& configRenderExperimentalJson = configRenderJson["experimental"];
auto& configRenderPipelinesJson = configRenderJson["pipelines"];
uf::renderer::settings::validation = configRenderJson["validation"]["enabled"].as( uf::renderer::settings::validation );
uf::renderer::settings::msaa = configRenderJson["framebuffer"]["msaa"].as( uf::renderer::settings::msaa );
@ -365,6 +369,11 @@ void EXT_API ext::initialize() {
}
#if UF_USE_VULKAN
if ( configRenderJson["gpu"].as<uf::stl::string>() == "auto" ) {
uf::renderer::settings::gpuID = -1;
} else {
uf::renderer::settings::gpuID = configRenderJson["gpu"].as(uf::renderer::settings::gpuID);
}
for ( int i = 0; i < configRenderJson["validation"]["filters"].size(); ++i ) {
uf::renderer::settings::validationFilters.emplace_back( configRenderJson["validation"]["filters"][i].as<uf::stl::string>() );
}
@ -377,21 +386,37 @@ void EXT_API ext::initialize() {
for ( int i = 0; i < configRenderJson["features"].size(); ++i ) {
uf::renderer::settings::requestedDeviceFeatures.emplace_back( configRenderJson["features"][i].as<uf::stl::string>() );
}
/*
"rebuild on tick begin": false,
"wait on render end": false,
"multithreaded recording": true,
"individual pipelines": true,
"deferred mode": "",
"deferred reconstruct position": true,
"deferred alias output to swapchain": false,
*/
::requestDedicatedRenderThread = configRenderExperimentalJson["dedicated thread"].as( uf::renderer::settings::experimental::dedicatedThread );
#if 0
uf::renderer::settings::experimental::dedicatedThread = configRenderExperimentalJson["dedicated thread"].as( uf::renderer::settings::experimental::dedicatedThread );
uf::renderer::settings::experimental::rebuildOnTickBegin = configRenderExperimentalJson["rebuild on tick begin"].as( uf::renderer::settings::experimental::rebuildOnTickBegin );
uf::renderer::settings::experimental::waitOnRenderEnd = configRenderExperimentalJson["wait on render end"].as( uf::renderer::settings::experimental::waitOnRenderEnd );
uf::renderer::settings::experimental::individualPipelines = configRenderExperimentalJson["individual pipelines"].as( uf::renderer::settings::experimental::individualPipelines );
uf::renderer::settings::experimental::multithreadedCommandRecording = configRenderExperimentalJson["multithreaded command recording"].as( uf::renderer::settings::experimental::multithreadedCommandRecording );
uf::renderer::settings::experimental::multithreadedCommandRendering = configRenderExperimentalJson["multithreaded command rendering"].as( uf::renderer::settings::experimental::multithreadedCommandRendering );
uf::renderer::settings::experimental::deferredMode = configRenderExperimentalJson["deferred mode"].as( uf::renderer::settings::experimental::deferredMode );
uf::renderer::settings::experimental::deferredReconstructPosition = configRenderExperimentalJson["deferred reconstruct position"].as( uf::renderer::settings::experimental::deferredReconstructPosition );
uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = configRenderExperimentalJson["deferred alias output to swapchain"].as( uf::renderer::settings::experimental::deferredAliasOutputToSwapchain );
uf::renderer::settings::experimental::vsync = configRenderExperimentalJson["vsync"].as( uf::renderer::settings::experimental::vsync );
uf::renderer::settings::experimental::hdr = configRenderExperimentalJson["hdr"].as( uf::renderer::settings::experimental::hdr );
uf::renderer::settings::experimental::vxgi = configRenderExperimentalJson["vxgi"].as( uf::renderer::settings::experimental::vxgi );
uf::renderer::settings::experimental::deferredSampling = configRenderExperimentalJson["deferred sampling"].as( uf::renderer::settings::experimental::deferredSampling );
uf::renderer::settings::experimental::culling = configRenderExperimentalJson["culling"].as( uf::renderer::settings::experimental::culling );
uf::renderer::settings::experimental::bloom = configRenderExperimentalJson["bloom"].as( uf::renderer::settings::experimental::bloom );
#endif
uf::renderer::settings::experimental::batchQueueSubmissions = configRenderExperimentalJson["batch queue submissions"].as( uf::renderer::settings::experimental::batchQueueSubmissions );
uf::renderer::settings::invariant::multithreadedRecording = configRenderInvariantJson["multithreaded recording"].as( uf::renderer::settings::invariant::multithreadedRecording );
uf::renderer::settings::invariant::waitOnRenderEnd = configRenderInvariantJson["wait on render end"].as( uf::renderer::settings::invariant::waitOnRenderEnd );
uf::renderer::settings::invariant::individualPipelines = configRenderInvariantJson["individual pipelines"].as( uf::renderer::settings::invariant::individualPipelines );
uf::renderer::settings::invariant::deferredMode = configRenderInvariantJson["deferred mode"].as( uf::renderer::settings::invariant::deferredMode );
uf::renderer::settings::invariant::deferredReconstructPosition = configRenderInvariantJson["deferred reconstruct position"].as( uf::renderer::settings::invariant::deferredReconstructPosition );
uf::renderer::settings::invariant::deferredAliasOutputToSwapchain = configRenderInvariantJson["deferred alias output to swapchain"].as( uf::renderer::settings::invariant::deferredAliasOutputToSwapchain );
uf::renderer::settings::invariant::deferredSampling = configRenderInvariantJson["deferred sampling"].as( uf::renderer::settings::invariant::deferredSampling );
uf::renderer::settings::pipelines::vsync = configRenderPipelinesJson["vsync"].as( uf::renderer::settings::pipelines::vsync );
uf::renderer::settings::pipelines::hdr = configRenderPipelinesJson["hdr"].as( uf::renderer::settings::pipelines::hdr );
uf::renderer::settings::pipelines::vxgi = configRenderPipelinesJson["vxgi"].as( uf::renderer::settings::pipelines::vxgi );
uf::renderer::settings::pipelines::culling = configRenderPipelinesJson["culling"].as( uf::renderer::settings::pipelines::culling );
uf::renderer::settings::pipelines::bloom = configRenderPipelinesJson["bloom"].as( uf::renderer::settings::pipelines::bloom );
#define JSON_TO_VKFORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
uf::stl::string format = configRenderJson["formats"][#key].as<uf::stl::string>();\
@ -446,7 +471,6 @@ void EXT_API ext::initialize() {
}
#endif
#if UF_USE_VULKAN
/* Initialize Vulkan */ {
// setup render mode
if ( ::json["engine"]["render modes"]["gui"].as<bool>(true) ) {
@ -460,10 +484,11 @@ void EXT_API ext::initialize() {
if ( ::json["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
renderMode.metadata.eyes = 2;
}
if ( uf::renderer::settings::experimental::culling ) {
if ( uf::renderer::settings::pipelines::culling ) {
renderMode.metadata.pipelines.emplace_back("culling");
}
}
#if UF_USE_VULKAN
/* Callbacks for 2KHR stuffs */ {
uf::hooks.addHook("vulkan:Instance.ExtensionsEnabled", []( const ext::json::Value& json ) {
// UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json);
@ -498,8 +523,8 @@ void EXT_API ext::initialize() {
// UF_MSG_DEBUG("\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex);
});
}
}
#endif
}
#if UF_USE_OPENVR
if ( ext::openvr::enabled ) {
ext::openvr::initialize();
@ -527,7 +552,7 @@ void EXT_API ext::initialize() {
uf::renderer::initialize();
}
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false );
pod::Thread& threadMain = uf::thread::get("Main");
#if UF_USE_DISCORD
/* Discord */ if ( ::config.engine.ext.discord.enabled ) {
ext::discord::initialize();
@ -555,7 +580,8 @@ void EXT_API ext::initialize() {
return 0;
};
if ( json["immediate"].as<bool>() ) function(); else uf::thread::add( uf::thread::get("Main"), function, true );
if ( json["immediate"].as<bool>() ) function();
else uf::thread::queue( uf::thread::get("Main"), function );
});
uf::hooks.addHook( "game:Scene.Cleanup", [&](ext::json::Value& json){
@ -577,11 +603,11 @@ void EXT_API ext::initialize() {
}
/*
uf::thread::add( uf::thread::fetchWorker(), [&]() -> int {
uf::thread::add( uf::thread::fetchWorker(), [&]{
auto& scene = uf::scene::getCurrentScene();
auto& assetLoader = scene.getComponent<uf::Asset>();
assetLoader.processQueue();
return 0;}, false );
});
*/
ext::ready = true;
@ -659,7 +685,7 @@ void EXT_API ext::tick() {
}
#endif
/* Update vulkan */ {
uf::renderer::tick();
// uf::renderer::tick();
}
//UF_TIMER_TRACE("ticking renderer");
#if UF_USE_DISCORD
@ -671,7 +697,7 @@ void EXT_API ext::tick() {
++::times.frames;
++::times.total.frames;
TIMER( ::config.engine.fps.every ) {
UF_MSG_DEBUG("System: " << (::config.engine.fps.every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
UF_MSG_DEBUG("System: " << (time * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
#if UF_ENV_DREAMCAST
DC_STATS();
#endif
@ -699,6 +725,13 @@ void EXT_API ext::tick() {
}
timer.reset();
}
if ( ::requestDedicatedRenderThread ) {
::requestDedicatedRenderThread = false;
uf::renderer::settings::experimental::dedicatedThread = true;
uf::renderer::settings::experimental::rebuildOnTickBegin = true;
UF_MSG_DEBUG("Dedicated render requested");
}
#endif
}
void EXT_API ext::render() {
@ -713,6 +746,7 @@ void EXT_API ext::render() {
}
#endif
/* Render scene */ {
uf::renderer::tick();
uf::renderer::render();
}
#if UF_USE_OPENVR

1
makefiles/default/arch Normal file
View File

@ -0,0 +1 @@
win64

1
makefiles/default/cc Normal file
View File

@ -0,0 +1 @@
gcc

View File

@ -0,0 +1 @@
vulkan

View File

@ -2,6 +2,7 @@ ARCH = dreamcast
CDIR =
CC = gcc
CXX = $(KOS_CCPLUS)
RENDERER = opengl
TARGET_EXTENSION = elf
OPTIMIZATIONS = -Os -g -ffunction-sections -fdata-sections -Wl,--gc-sections -fstrict-aliasing -ffast-math -flto -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer -DUF_NO_EXCEPTIONS -fno-exceptions
WARNINGS = -Wno-attributes -Wno-conversion-null

View File

@ -3,5 +3,5 @@ CDIR =
CC = clang
CXX = clang++
OPTIMIZATIONS = -O3 -fstrict-aliasing # -flto
WARNINGS = -g -Wall -Wno-pointer-arith -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder-ctor -Wno-ignored-attributes -Wno-c++11-narrowing -Wno-unknown-pragmas
WARNINGS = -g -Wall -Wno-pointer-arith -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder-ctor -Wno-ignored-attributes -Wno-c++11-narrowing -Wno-unknown-pragmas -Wno-nullability-completeness -Wno-defaulted-function-deleted -Wno-mismatched-tags
FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fcolor-diagnostics -fansi-escape-codes

View File

@ -2,6 +2,6 @@ ARCH = win64
CDIR =
CC = gcc
CXX = g++
OPTIMIZATIONS = -O3 -g -fstrict-aliasing #-flto
OPTIMIZATIONS = -g -O3 -fstrict-aliasing #-flto
WARNINGS = -Wall -Wno-unknown-pragmas -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation
FLAGS += -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always
FLAGS += -std=c++20 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always