From cf3d1eebc1dd5c525a298fe2b7a6702f782b9a5e Mon Sep 17 00:00:00 2001 From: mrq Date: Mon, 9 May 2022 00:07:00 -0500 Subject: [PATCH] Commit for 2022.05.09 00-07-22.7z --- Makefile | 12 +- bin/data/config.json | 9 +- bin/data/entities/model.json | 7 +- bin/data/scenes/ss2/medsci.json | 20 +- bin/data/shaders/common/structs.h | 4 +- bin/data/shaders/graph/baking/bake.frag.glsl | 22 +- bin/data/shaders/graph/baking/bake.geom.glsl | 42 +++ bin/data/shaders/graph/baking/bake.vert.glsl | 1 + bin/data/shaders/graph/base.frag.h | 8 +- bin/data/shaders/graph/base.vert.h | 19 +- bin/data/shaders/graph/depth.frag.glsl | 8 +- bin/data/shaders/graph/voxelize.frag.h | 25 +- bin/data/shaders/graph/voxelize.geom.glsl | 2 +- .../scene}/construct/gm_construct.json | 0 .../scene}/construct/loading.json | 0 .../scene}/construct/player.json | 0 .../scene}/construct/scene.json | 0 .../scene}/mcdonalds/craeture.json | 0 .../scene}/mcdonalds/door.json | 0 .../scene}/mcdonalds/loading.json | 0 .../scene}/mcdonalds/marker.json | 0 .../scene}/mcdonalds/mcdonalds.json | 0 .../scene}/mcdonalds/player.json | 0 .../scene}/mcdonalds/scene.json | 0 .../scene}/mcdonalds/scripts/door.lua | 0 .../scene}/mcdonalds/scripts/realign.lua | 0 .../scene}/mcdonalds/scripts/static.lua | 0 .../scene}/mcdonalds/sound.json | 0 .../scene}/mcdonalds/static.json | 0 .../scene}/sh2_mcdonalds/craeture.json | 0 .../scene}/sh2_mcdonalds/door.json | 0 .../scene}/sh2_mcdonalds/loading.json | 0 .../scene}/sh2_mcdonalds/marker.json | 0 .../scene}/sh2_mcdonalds/player.json | 0 .../scene}/sh2_mcdonalds/playerLight.json | 0 .../scene}/sh2_mcdonalds/prop.json | 0 .../scene}/sh2_mcdonalds/scene.json | 0 .../scene}/sh2_mcdonalds/scripts/door.lua | 0 .../scene}/sh2_mcdonalds/scripts/realign.lua | 0 .../scene}/sh2_mcdonalds/scripts/static.lua | 0 .../sh2_mcdonalds/scripts/trackPlayer.lua | 0 .../scene}/sh2_mcdonalds/sh2_mcdonalds.json | 0 .../scene}/sh2_mcdonalds/sound.json | 0 .../scene}/sh2_mcdonalds/static.json | 0 bin/data2/scene/ss2/ambience.json | 12 + bin/data2/scene/ss2/camera.json | 13 + bin/data2/scene/ss2/craeture.json | 16 + bin/data2/scene/ss2/lift.json | 13 + bin/data2/scene/ss2/loading.json | 32 ++ bin/data2/scene/ss2/medsci.json | 58 ++++ bin/data2/scene/ss2/noise.json | 18 + bin/data2/scene/ss2/player.json | 27 ++ bin/data2/scene/ss2/scene.json | 55 +++ bin/data2/scene/ss2/scripts/camera.lua | 191 +++++++++++ bin/data2/scene/ss2/scripts/lift.lua | 84 +++++ bin/data2/scene/ss2/sound.json | 34 ++ bin/dreamcast/config.json | 6 +- client/main.cpp | 6 +- engine/inc/uf/ext/vulkan/rendermode.h | 3 +- engine/inc/uf/ext/vulkan/rendertarget.h | 1 + engine/inc/uf/ext/vulkan/texture.h | 4 + engine/inc/uf/ext/xatlas/xatlas.h | 3 +- engine/inc/uf/macros.h | 9 +- engine/inc/uf/spec/window/dreamcast.h | 13 +- engine/inc/uf/spec/window/universal.h | 14 +- engine/inc/uf/spec/window/windows.h | 13 +- engine/inc/uf/utils/mesh/grid.h | 5 +- engine/inc/uf/utils/mesh/mesh.h | 18 +- engine/inc/uf/utils/window/window.h | 59 +--- engine/src/engine/graph/decode.cpp | 13 +- engine/src/engine/graph/encode.cpp | 10 +- engine/src/engine/graph/graph.cpp | 153 ++++++--- engine/src/ext/gltf/gltf.cpp | 15 +- engine/src/ext/gltf/processPrimitives2.inl | 11 +- engine/src/ext/opengl/commands.cpp | 3 +- engine/src/ext/opengl/device.cpp | 2 +- engine/src/ext/opengl/rendermodes/base.cpp | 3 +- engine/src/ext/opengl/texture.cpp | 18 +- engine/src/ext/vulkan/device.cpp | 6 + engine/src/ext/vulkan/graphic.cpp | 16 + engine/src/ext/vulkan/rendermode.cpp | 15 +- .../ext/vulkan/rendermodes/rendertarget.cpp | 1 + engine/src/ext/vulkan/rendertarget.cpp | 5 +- engine/src/ext/vulkan/texture.cpp | 234 +++++++++++++ engine/src/ext/xatlas/xatlas.cpp | 323 ++++++++++-------- engine/src/spec/window/dreamcast.cpp | 268 +++++++++------ engine/src/spec/window/universal.cpp | 6 +- engine/src/spec/window/windows.cpp | 32 +- engine/src/utils/mesh/mesh.cpp | 4 +- engine/src/utils/window/window.cpp | 175 ---------- ext/behaviors/baking/behavior.cpp | 19 +- ext/behaviors/baking/behavior.h | 2 + ext/behaviors/scene/behavior.cpp | 122 ++++--- ext/main.cpp | 3 + makefiles/dreamcast.gcc.make | 2 +- makefiles/win64.gcc.make | 2 +- 96 files changed, 1679 insertions(+), 670 deletions(-) create mode 100644 bin/data/shaders/graph/baking/bake.geom.glsl rename bin/{data/scenes => data2/scene}/construct/gm_construct.json (100%) rename bin/{data/scenes => data2/scene}/construct/loading.json (100%) rename bin/{data/scenes => data2/scene}/construct/player.json (100%) rename bin/{data/scenes => data2/scene}/construct/scene.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/craeture.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/door.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/loading.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/marker.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/mcdonalds.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/player.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/scene.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/scripts/door.lua (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/scripts/realign.lua (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/scripts/static.lua (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/sound.json (100%) rename bin/{data/scenes => data2/scene}/mcdonalds/static.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/craeture.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/door.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/loading.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/marker.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/player.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/playerLight.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/prop.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/scene.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/scripts/door.lua (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/scripts/realign.lua (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/scripts/static.lua (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/scripts/trackPlayer.lua (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/sh2_mcdonalds.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/sound.json (100%) rename bin/{data/scenes => data2/scene}/sh2_mcdonalds/static.json (100%) create mode 100644 bin/data2/scene/ss2/ambience.json create mode 100644 bin/data2/scene/ss2/camera.json create mode 100644 bin/data2/scene/ss2/craeture.json create mode 100644 bin/data2/scene/ss2/lift.json create mode 100644 bin/data2/scene/ss2/loading.json create mode 100644 bin/data2/scene/ss2/medsci.json create mode 100644 bin/data2/scene/ss2/noise.json create mode 100644 bin/data2/scene/ss2/player.json create mode 100644 bin/data2/scene/ss2/scene.json create mode 100644 bin/data2/scene/ss2/scripts/camera.lua create mode 100644 bin/data2/scene/ss2/scripts/lift.lua create mode 100644 bin/data2/scene/ss2/sound.json delete mode 100644 engine/src/utils/window/window.cpp diff --git a/Makefile b/Makefile index 5e6a5fdc..422d8bef 100644 --- a/Makefile +++ b/Makefile @@ -51,11 +51,11 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS) DEPS += ifneq (,$(findstring win64,$(ARCH))) - REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype curl luajit reactphysics meshoptimizer xatlas simd ctti # ncurses openvr draco discord bullet ultralight-ux + 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 else ifneq (,$(findstring dreamcast,$(ARCH))) - REQ_DEPS += simd opengl gldc json:nlohmann lua reactphysics png zlib ctti ogg openal aldc # freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord + REQ_DEPS += simd opengl gldc json:nlohmann lua reactphysics png zlib ctti ogg openal aldc # gltf freetype bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord endif ifneq (,$(findstring vulkan,$(REQ_DEPS))) FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN @@ -91,6 +91,9 @@ ifneq (,$(findstring json,$(REQ_DEPS))) FLAGS += -DUF_JSON_USE_NLOHMANN endif endif +ifneq (,$(findstring gltf,$(REQ_DEPS))) + FLAGS += -DUF_USE_GLTF +endif ifneq (,$(findstring png,$(REQ_DEPS))) FLAGS += -DUF_USE_PNG -DUF_USE_ZLIB DEPS += -lpng -lz @@ -252,9 +255,8 @@ $(EXT_EX_DLL): $(OBJS_EXT_DLL) $(KOS_BASE)/utils/bin2o/bin2o ./bin/dreamcast/romdisk.img romdisk ./bin/dreamcast/romdisk.o $(TARGET): $(OBJS) #./bin/dreamcast/romdisk.o -# $(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) ./bin/dreamcast/romdisk.o -Wl,--start-group $(DEPS) -Wl,--end-group -# $(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group - $(CXX) -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group + $(CXX) $(FLAGS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group + # $(KOS_STRIP) --strip-unneeded $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi: $(TARGET) cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME) diff --git a/bin/data/config.json b/bin/data/config.json index eca8d8f3..c88c2200 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -51,6 +51,10 @@ "MessageID = 0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197 "MessageID = 0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973 + // "MessageID = 0x8e1000ad", // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor) + // "MessageID = 0x9dd97212", // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor) + // "MessageID = 0x36481fcb", // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor) + "MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps) // "MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup) "MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls) @@ -101,6 +105,8 @@ "nullDescriptor", "fragmentStoresAndAtomics", "geometryShader", + "multiViewport", + "shaderOutputLayer", // "shaderUniformBufferArrayDynamicIndexing", // "shaderStorageBufferArrayDynamicIndexing", "shaderSampledImageArrayDynamicIndexing", @@ -112,7 +118,8 @@ "VK_KHR_get_surface_capabilities2" ], "device": [ - "VK_KHR_swapchain" + "VK_KHR_swapchain", + "VK_EXT_shader_viewport_index_layer" ] } }, diff --git a/bin/data/entities/model.json b/bin/data/entities/model.json index ea81cbcc..dd7a6d51 100644 --- a/bin/data/entities/model.json +++ b/bin/data/entities/model.json @@ -29,8 +29,9 @@ "enabled": false, "resolution": 8192, "shadows": 1024, + "layers": 1, "trigger": { "mode": "rendered" }, - "output": "./lightmap.png" + "output": "./lightmap.%i.png" }, "grid": { "/^worldspawn/": { @@ -40,8 +41,8 @@ "print": true } }, - // "lightmap": "./lightmap.min.png", - // "lightmap": "./lightmap.png", + // "lightmap": "./lightmap.%i.min.png", + // "lightmap": "./lightmap.%i.png", // "filter": "NEAREST", "flags": { "ATLAS": false, diff --git a/bin/data/scenes/ss2/medsci.json b/bin/data/scenes/ss2/medsci.json index 673261ff..ec31a1cb 100644 --- a/bin/data/scenes/ss2/medsci.json +++ b/bin/data/scenes/ss2/medsci.json @@ -8,6 +8,7 @@ // { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./craeture.json", "delay": 1 } // { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" } @@ -21,17 +22,26 @@ "metadata": { "model": { "exporter": { - "enabled": false + "enabled": true }, "baking": { "enabled": false, - "resolution": 8192, + "resolution": 2048, // 8192 "shadows": 1024, + "layers": 22, "trigger": { "mode": "rendered" }, - "output": "./lightmap.png" + // "trigger": { "mode": "key", "value": "B" }, + "output": "./lightmap.%i.png" }, - // "lightmap": "./lightmap.min.png", - "filter": "NEAREST", + "grid": { + "/^worldspawn/": { + "size": [3,3,3] + } + }, +// "lightmap": "./lightmap.%i.min.png", +// "lightmap": false, + "lightmap": true, + "filter": "LINEAR", "tags": { "worldspawn": { "physics": { "type": "mesh", "static": true } }, "worldspawn_20": { "physics": { "type": "mesh", "static": true } }, diff --git a/bin/data/shaders/common/structs.h b/bin/data/shaders/common/structs.h index fe377eed..bd7e935e 100644 --- a/bin/data/shaders/common/structs.h +++ b/bin/data/shaders/common/structs.h @@ -107,7 +107,7 @@ struct DrawCommand { int vertexID; // starting vertex position uint instanceID; // starting instance position - uint padding; // + uint auxID; // uint materialID; // material to use for this draw call uint vertices; // number of vertices used }; @@ -131,7 +131,7 @@ struct Instance { int jointID; int lightmapID; uint imageID; - uint padding2; + uint auxID; Bounds bounds; }; diff --git a/bin/data/shaders/graph/baking/bake.frag.glsl b/bin/data/shaders/graph/baking/bake.frag.glsl index ed68abff..fcb09737 100644 --- a/bin/data/shaders/graph/baking/bake.frag.glsl +++ b/bin/data/shaders/graph/baking/bake.frag.glsl @@ -5,9 +5,10 @@ layout (constant_id = 0) const uint TEXTURES = 512; layout (constant_id = 1) const uint CUBEMAPS = 128; +layout (constant_id = 2) const uint LAYERS = 32; -layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES]; -layout (binding = 5) uniform samplerCube samplerCubemaps[CUBEMAPS]; +layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; +layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS]; #define SHADOW_SAMPLES 16 #define FRAGMENT 1 @@ -18,19 +19,21 @@ layout (binding = 5) uniform samplerCube samplerCubemaps[CUBEMAPS]; #include "../../common/macros.h" #include "../../common/structs.h" -layout (std140, binding = 6) readonly buffer Instances { +layout (std140, binding = 7) readonly buffer Instances { Instance instances[]; }; -layout (std140, binding = 7) readonly buffer Materials { +layout (std140, binding = 8) readonly buffer Materials { Material materials[]; }; -layout (std140, binding = 8) readonly buffer Textures { +layout (std140, binding = 9) readonly buffer Textures { Texture textures[]; }; -layout (std140, binding = 9) readonly buffer Lights { +layout (std140, binding = 10) readonly buffer Lights { Light lights[]; }; +layout (binding = 11, rgba8) uniform volatile coherent image3D outAlbedos; + #include "../../common/functions.h" #include "../../common/shadows.h" #if PBR @@ -44,6 +47,7 @@ layout (location = 3) in vec3 inNormal; layout (location = 4) in mat3 inTBN; layout (location = 7) in vec3 inPosition; layout (location = 8) flat in uvec4 inId; +layout (location = 9) flat in uint inLayer; layout (location = 0) out vec4 outAlbedo; @@ -115,4 +119,10 @@ void main() { // surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / GAMMA)); outAlbedo = vec4(surface.fragment.rgb, 1); + + { + const vec2 st = inSt.xy * imageSize(outAlbedos).xy; + const ivec3 uvw = ivec3(int(st.x), int(st.y), int(inLayer)); + imageStore(outAlbedos, uvw, vec4(surface.fragment.rgb, 1) ); + } } \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/bake.geom.glsl b/bin/data/shaders/graph/baking/bake.geom.glsl new file mode 100644 index 00000000..55be062a --- /dev/null +++ b/bin/data/shaders/graph/baking/bake.geom.glsl @@ -0,0 +1,42 @@ +#version 450 +#pragma shader_stage(geometry) + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +layout (location = 0) in vec2 inUv[]; +layout (location = 1) in vec2 inSt[]; +layout (location = 2) in vec4 inColor[]; +layout (location = 3) in vec3 inNormal[]; +layout (location = 4) in mat3 inTBN[]; +layout (location = 7) in vec3 inPosition[]; +layout (location = 8) flat in uvec4 inId[]; +layout (location = 9) flat in uint inLayer[]; + +layout (location = 0) out vec2 outUv; +layout (location = 1) out vec2 outSt; +layout (location = 2) out vec4 outColor; +layout (location = 3) out vec3 outNormal; +layout (location = 4) out mat3 outTBN; +layout (location = 7) out vec3 outPosition; +layout (location = 8) flat out uvec4 outId; +layout (location = 9) flat out uint outLayer; + +void main(){ + for( uint i = 0; i < 3; ++i ){ + outUv = inUv[i]; + outSt = inSt[i]; + outColor = inColor[i]; + outNormal = inNormal[i]; + outTBN = inTBN[i]; + outPosition = inPosition[i]; + outId = inId[i]; + outLayer = inLayer[i]; + + gl_Position = vec4(inSt[i] * 2.0 - 1.0, 0.0, 1.0); + gl_Layer = int(inLayer[i]); + + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/bin/data/shaders/graph/baking/bake.vert.glsl b/bin/data/shaders/graph/baking/bake.vert.glsl index 7e5ae878..e1cfbca8 100644 --- a/bin/data/shaders/graph/baking/bake.vert.glsl +++ b/bin/data/shaders/graph/baking/bake.vert.glsl @@ -4,5 +4,6 @@ #define INSTANCED 1 #define SKINNED 0 #define BAKING 1 +#define LAYERED 1 #include "../base.vert.h" diff --git a/bin/data/shaders/graph/base.frag.h b/bin/data/shaders/graph/base.frag.h index 2e8782ad..12180284 100644 --- a/bin/data/shaders/graph/base.frag.h +++ b/bin/data/shaders/graph/base.frag.h @@ -8,14 +8,14 @@ layout (constant_id = 0) const uint TEXTURES = 1; #include "../common/macros.h" #include "../common/structs.h" -layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES]; -layout (std140, binding = 5) readonly buffer Instances { +layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; +layout (std140, binding = 6) readonly buffer Instances { Instance instances[]; }; -layout (std140, binding = 6) readonly buffer Materials { +layout (std140, binding = 7) readonly buffer Materials { Material materials[]; }; -layout (std140, binding = 7) readonly buffer Textures { +layout (std140, binding = 8) readonly buffer Textures { Texture textures[]; }; diff --git a/bin/data/shaders/graph/base.vert.h b/bin/data/shaders/graph/base.vert.h index 45e6fd77..e8965b5f 100644 --- a/bin/data/shaders/graph/base.vert.h +++ b/bin/data/shaders/graph/base.vert.h @@ -1,5 +1,8 @@ layout (constant_id = 0) const uint PASSES = 6; #extension GL_ARB_shader_draw_parameters : enable +#if LAYERED +#extension GL_ARB_shader_viewport_layer_array : enable +#endif #include "../common/structs.h" layout (location = 0) in vec3 inPos; @@ -23,17 +26,15 @@ layout (binding = 0) uniform Camera { Viewport viewport[PASSES]; } camera; #endif -/* layout (std140, binding = 1) readonly buffer DrawCommands { DrawCommand drawCommands[]; }; -*/ -layout (std140, binding = 1) readonly buffer Instances { +layout (std140, binding = 2) readonly buffer Instances { Instance instances[]; }; #if SKINNED - layout (std140, binding = 2) readonly buffer Joints { + layout (std140, binding = 3) readonly buffer Joints { mat4 joints[]; }; #endif @@ -45,6 +46,9 @@ layout (location = 3) out vec3 outNormal; layout (location = 4) out mat3 outTBN; layout (location = 7) out vec3 outPosition; layout (location = 8) out uvec4 outId; +#if LAYERED + layout (location = 9) out uint outLayer; +#endif vec4 snap(vec4 vertex, vec2 resolution) { vec4 snappedPos = vertex; @@ -58,7 +62,7 @@ void main() { outUv = inUv; outSt = inSt; const uint drawID = gl_DrawIDARB; -// const DrawCommand drawCommand = drawCommands[drawID]; + const DrawCommand drawCommand = drawCommands[drawID]; const uint instanceID = gl_InstanceIndex; const Instance instance = instances[instanceID]; const uint materialID = instance.materialID; @@ -94,4 +98,9 @@ void main() { #else gl_Position = projection * view * model * vec4(inPos.xyz, 1.0); #endif + +#if LAYERED +// gl_Layer = int(drawCommand.auxID); + outLayer = int(drawCommand.auxID); +#endif } \ No newline at end of file diff --git a/bin/data/shaders/graph/depth.frag.glsl b/bin/data/shaders/graph/depth.frag.glsl index 5fcd9e00..7ebdadd6 100644 --- a/bin/data/shaders/graph/depth.frag.glsl +++ b/bin/data/shaders/graph/depth.frag.glsl @@ -10,14 +10,14 @@ layout (constant_id = 0) const uint TEXTURES = 1; #include "../common/macros.h" #include "../common/structs.h" -layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES]; -layout (std140, binding = 5) readonly buffer Instances { +layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; +layout (std140, binding = 6) readonly buffer Instances { Instance instances[]; }; -layout (std140, binding = 6) readonly buffer Materials { +layout (std140, binding = 7) readonly buffer Materials { Material materials[]; }; -layout (std140, binding = 7) readonly buffer Textures { +layout (std140, binding = 8) readonly buffer Textures { Texture textures[]; }; diff --git a/bin/data/shaders/graph/voxelize.frag.h b/bin/data/shaders/graph/voxelize.frag.h index 2e70581a..168e50f3 100644 --- a/bin/data/shaders/graph/voxelize.frag.h +++ b/bin/data/shaders/graph/voxelize.frag.h @@ -10,26 +10,26 @@ layout (constant_id = 1) const uint CASCADES = 16; #include "../common/macros.h" #include "../common/structs.h" -layout (binding = 4) uniform sampler2D samplerTextures[TEXTURES]; -layout (std140, binding = 5) readonly buffer Instances { +layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES]; +layout (std140, binding = 6) readonly buffer Instances { Instance instances[]; }; -layout (std140, binding = 6) readonly buffer Materials { +layout (std140, binding = 7) readonly buffer Materials { Material materials[]; }; -layout (std140, binding = 7) readonly buffer Textures { +layout (std140, binding = 8) readonly buffer Textures { Texture textures[]; }; -layout (binding = 8, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES]; -layout (binding = 9, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES]; +layout (binding = 9, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES]; +layout (binding = 10, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES]; #if VXGI_HDR - layout (binding = 10, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES]; + layout (binding = 11, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES]; #else - layout (binding = 10, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES]; + layout (binding = 11, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES]; #endif #if DEPTH_TEST - layout (binding = 11, r16f) uniform volatile coherent image3D voxelDepth[CASCADES]; + layout (binding = 12, r16f) uniform volatile coherent image3D voxelDepth[CASCADES]; #endif layout (location = 0) in vec2 inUv; @@ -81,12 +81,7 @@ void main() { // sample albedo if ( !validTextureIndex( material.indexAlbedo ) ) discard; { - if ( surface.instance.imageID <= 0 ) { - A = sampleTexture( material.indexAlbedo ); - } else { - const Texture t = textures[material.indexAlbedo]; - A = texture( samplerTextures[nonuniformEXT(t.index - surface.instance.imageID)], mix( t.lerp.xy, t.lerp.zw, uv ) ); - } + A = sampleTexture( material.indexAlbedo ); // alpha mode OPAQUE if ( material.modeAlpha == 0 ) { A.a = 1; diff --git a/bin/data/shaders/graph/voxelize.geom.glsl b/bin/data/shaders/graph/voxelize.geom.glsl index 44e63410..0f7791f8 100644 --- a/bin/data/shaders/graph/voxelize.geom.glsl +++ b/bin/data/shaders/graph/voxelize.geom.glsl @@ -20,7 +20,7 @@ layout (location = 4) out mat3 outTBN; layout (location = 7) out vec3 outPosition; layout (location = 8) flat out uvec4 outId; -layout (binding = 3) uniform UBO { +layout (binding = 4) uniform UBO { mat4 voxel; float cascadePower; float padding1; diff --git a/bin/data/scenes/construct/gm_construct.json b/bin/data2/scene/construct/gm_construct.json similarity index 100% rename from bin/data/scenes/construct/gm_construct.json rename to bin/data2/scene/construct/gm_construct.json diff --git a/bin/data/scenes/construct/loading.json b/bin/data2/scene/construct/loading.json similarity index 100% rename from bin/data/scenes/construct/loading.json rename to bin/data2/scene/construct/loading.json diff --git a/bin/data/scenes/construct/player.json b/bin/data2/scene/construct/player.json similarity index 100% rename from bin/data/scenes/construct/player.json rename to bin/data2/scene/construct/player.json diff --git a/bin/data/scenes/construct/scene.json b/bin/data2/scene/construct/scene.json similarity index 100% rename from bin/data/scenes/construct/scene.json rename to bin/data2/scene/construct/scene.json diff --git a/bin/data/scenes/mcdonalds/craeture.json b/bin/data2/scene/mcdonalds/craeture.json similarity index 100% rename from bin/data/scenes/mcdonalds/craeture.json rename to bin/data2/scene/mcdonalds/craeture.json diff --git a/bin/data/scenes/mcdonalds/door.json b/bin/data2/scene/mcdonalds/door.json similarity index 100% rename from bin/data/scenes/mcdonalds/door.json rename to bin/data2/scene/mcdonalds/door.json diff --git a/bin/data/scenes/mcdonalds/loading.json b/bin/data2/scene/mcdonalds/loading.json similarity index 100% rename from bin/data/scenes/mcdonalds/loading.json rename to bin/data2/scene/mcdonalds/loading.json diff --git a/bin/data/scenes/mcdonalds/marker.json b/bin/data2/scene/mcdonalds/marker.json similarity index 100% rename from bin/data/scenes/mcdonalds/marker.json rename to bin/data2/scene/mcdonalds/marker.json diff --git a/bin/data/scenes/mcdonalds/mcdonalds.json b/bin/data2/scene/mcdonalds/mcdonalds.json similarity index 100% rename from bin/data/scenes/mcdonalds/mcdonalds.json rename to bin/data2/scene/mcdonalds/mcdonalds.json diff --git a/bin/data/scenes/mcdonalds/player.json b/bin/data2/scene/mcdonalds/player.json similarity index 100% rename from bin/data/scenes/mcdonalds/player.json rename to bin/data2/scene/mcdonalds/player.json diff --git a/bin/data/scenes/mcdonalds/scene.json b/bin/data2/scene/mcdonalds/scene.json similarity index 100% rename from bin/data/scenes/mcdonalds/scene.json rename to bin/data2/scene/mcdonalds/scene.json diff --git a/bin/data/scenes/mcdonalds/scripts/door.lua b/bin/data2/scene/mcdonalds/scripts/door.lua similarity index 100% rename from bin/data/scenes/mcdonalds/scripts/door.lua rename to bin/data2/scene/mcdonalds/scripts/door.lua diff --git a/bin/data/scenes/mcdonalds/scripts/realign.lua b/bin/data2/scene/mcdonalds/scripts/realign.lua similarity index 100% rename from bin/data/scenes/mcdonalds/scripts/realign.lua rename to bin/data2/scene/mcdonalds/scripts/realign.lua diff --git a/bin/data/scenes/mcdonalds/scripts/static.lua b/bin/data2/scene/mcdonalds/scripts/static.lua similarity index 100% rename from bin/data/scenes/mcdonalds/scripts/static.lua rename to bin/data2/scene/mcdonalds/scripts/static.lua diff --git a/bin/data/scenes/mcdonalds/sound.json b/bin/data2/scene/mcdonalds/sound.json similarity index 100% rename from bin/data/scenes/mcdonalds/sound.json rename to bin/data2/scene/mcdonalds/sound.json diff --git a/bin/data/scenes/mcdonalds/static.json b/bin/data2/scene/mcdonalds/static.json similarity index 100% rename from bin/data/scenes/mcdonalds/static.json rename to bin/data2/scene/mcdonalds/static.json diff --git a/bin/data/scenes/sh2_mcdonalds/craeture.json b/bin/data2/scene/sh2_mcdonalds/craeture.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/craeture.json rename to bin/data2/scene/sh2_mcdonalds/craeture.json diff --git a/bin/data/scenes/sh2_mcdonalds/door.json b/bin/data2/scene/sh2_mcdonalds/door.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/door.json rename to bin/data2/scene/sh2_mcdonalds/door.json diff --git a/bin/data/scenes/sh2_mcdonalds/loading.json b/bin/data2/scene/sh2_mcdonalds/loading.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/loading.json rename to bin/data2/scene/sh2_mcdonalds/loading.json diff --git a/bin/data/scenes/sh2_mcdonalds/marker.json b/bin/data2/scene/sh2_mcdonalds/marker.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/marker.json rename to bin/data2/scene/sh2_mcdonalds/marker.json diff --git a/bin/data/scenes/sh2_mcdonalds/player.json b/bin/data2/scene/sh2_mcdonalds/player.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/player.json rename to bin/data2/scene/sh2_mcdonalds/player.json diff --git a/bin/data/scenes/sh2_mcdonalds/playerLight.json b/bin/data2/scene/sh2_mcdonalds/playerLight.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/playerLight.json rename to bin/data2/scene/sh2_mcdonalds/playerLight.json diff --git a/bin/data/scenes/sh2_mcdonalds/prop.json b/bin/data2/scene/sh2_mcdonalds/prop.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/prop.json rename to bin/data2/scene/sh2_mcdonalds/prop.json diff --git a/bin/data/scenes/sh2_mcdonalds/scene.json b/bin/data2/scene/sh2_mcdonalds/scene.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/scene.json rename to bin/data2/scene/sh2_mcdonalds/scene.json diff --git a/bin/data/scenes/sh2_mcdonalds/scripts/door.lua b/bin/data2/scene/sh2_mcdonalds/scripts/door.lua similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/scripts/door.lua rename to bin/data2/scene/sh2_mcdonalds/scripts/door.lua diff --git a/bin/data/scenes/sh2_mcdonalds/scripts/realign.lua b/bin/data2/scene/sh2_mcdonalds/scripts/realign.lua similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/scripts/realign.lua rename to bin/data2/scene/sh2_mcdonalds/scripts/realign.lua diff --git a/bin/data/scenes/sh2_mcdonalds/scripts/static.lua b/bin/data2/scene/sh2_mcdonalds/scripts/static.lua similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/scripts/static.lua rename to bin/data2/scene/sh2_mcdonalds/scripts/static.lua diff --git a/bin/data/scenes/sh2_mcdonalds/scripts/trackPlayer.lua b/bin/data2/scene/sh2_mcdonalds/scripts/trackPlayer.lua similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/scripts/trackPlayer.lua rename to bin/data2/scene/sh2_mcdonalds/scripts/trackPlayer.lua diff --git a/bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json b/bin/data2/scene/sh2_mcdonalds/sh2_mcdonalds.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/sh2_mcdonalds.json rename to bin/data2/scene/sh2_mcdonalds/sh2_mcdonalds.json diff --git a/bin/data/scenes/sh2_mcdonalds/sound.json b/bin/data2/scene/sh2_mcdonalds/sound.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/sound.json rename to bin/data2/scene/sh2_mcdonalds/sound.json diff --git a/bin/data/scenes/sh2_mcdonalds/static.json b/bin/data2/scene/sh2_mcdonalds/static.json similarity index 100% rename from bin/data/scenes/sh2_mcdonalds/static.json rename to bin/data2/scene/sh2_mcdonalds/static.json diff --git a/bin/data2/scene/ss2/ambience.json b/bin/data2/scene/ss2/ambience.json new file mode 100644 index 00000000..9724fb9e --- /dev/null +++ b/bin/data2/scene/ss2/ambience.json @@ -0,0 +1,12 @@ +{ + "behaviors": [ "SoundEmitterBehavior" ], + "metadata": { + "audio": { + "spatial": true, + "loop": true, + "volume": 1, + "rolloffFactor": 1, + "streamed": true + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/camera.json b/bin/data2/scene/ss2/camera.json new file mode 100644 index 00000000..20a35341 --- /dev/null +++ b/bin/data2/scene/ss2/camera.json @@ -0,0 +1,13 @@ +{ + "assets": [ + "./scripts/camera.lua", + "./audio/soundscape/camera.ogg" + ], + "metadata": { + "audio": { + "rolloffFactor": 4, + "volume": 1.0 + }, + "sensitivity": 10 + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/craeture.json b/bin/data2/scene/ss2/craeture.json new file mode 100644 index 00000000..b8dbef80 --- /dev/null +++ b/bin/data2/scene/ss2/craeture.json @@ -0,0 +1,16 @@ +{ + "name": "Craeture", + "behaviors": [ "CraetureBehavior" ], + "assets": [ + "./textures/craeture.png" + ], + "transform": { + "position": [18.3785, 2.41477, 0.859857], + "scale": [8, 8, 8] + }, + "metadata": { + "model": { + "cull mode": "none" + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/lift.json b/bin/data2/scene/ss2/lift.json new file mode 100644 index 00000000..4fa0e75d --- /dev/null +++ b/bin/data2/scene/ss2/lift.json @@ -0,0 +1,13 @@ +{ + "assets": [ "./scripts/lift.lua" ], + "system": { + "physics": { + "type": "bounding box", + "recenter": true, + + "mass": 100, + "restitution": 0, + "friction": 1 + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/loading.json b/bin/data2/scene/ss2/loading.json new file mode 100644 index 00000000..84c3288a --- /dev/null +++ b/bin/data2/scene/ss2/loading.json @@ -0,0 +1,32 @@ +{ + "name": "Gui: Loading", + "type": "Object", + "behaviors": [ + "GuiBehavior" + ], + "assets": [ + { "filename": "./medsci.json", "delay": 0 } + ], + "ignore": false, + "transform": { + "position": [ -0.830591, -0.699509, 0 ], + "rotation": { + "axis": [ 1, 0, 0 ], + "angle": 0 + }, + "scale": [ 0.258737, 0.115371, 1 ] + }, + "metadata": { + "uv": [ 0, 0, 1, 1 ], + "color": [ 1, 1, 1, 0.1 ], + "location": "", + "scaling": "relative", + "text settings": { + "stroke": [ 1, 0.749, 0.368, 1 ], + "color": [ 1, 0.749, 0.368, 1 ], + + "string": "Loading...", + "string1": "コマンド" + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/medsci.json b/bin/data2/scene/ss2/medsci.json new file mode 100644 index 00000000..673261ff --- /dev/null +++ b/bin/data2/scene/ss2/medsci.json @@ -0,0 +1,58 @@ +{ + "import": "/model.json", + "assets": [ + // { "filename": "./models/tiny_msci.glb", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/tiny_msci/graph.json", "delay": 0, "single threaded": false, "category": "models" } + { "filename": "./models/tiny_msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } + + // { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./craeture.json", "delay": 1 } + + // { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/msci/graph.json", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/msci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } + + // { "filename": "./models/medsci.glb", "delay": 0, "single threaded": false } + // { "filename": "./models/medsci/graph.json", "delay": 0, "single threaded": false, "category": "models" } + // { "filename": "./models/medsci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } + ], + "metadata": { + "model": { + "exporter": { + "enabled": false + }, + "baking": { + "enabled": false, + "resolution": 8192, + "shadows": 1024, + "trigger": { "mode": "rendered" }, + "output": "./lightmap.png" + }, + // "lightmap": "./lightmap.min.png", + "filter": "NEAREST", + "tags": { + "worldspawn": { "physics": { "type": "mesh", "static": true } }, + "worldspawn_20": { "physics": { "type": "mesh", "static": true } }, + // "worldspawn": { "physics": { "type": "bounding boxes", "static": true } }, + "info_player_spawn": { + "action": "attach", + "filename": "./player.json", + "preserve orientation": true + }, + "ambience_xerxes": { "action": "load", "payload": { "import": "./ambience.json", "assets": [ "./audio/soundscape/xerxes.ogg" ], "metadata": { "audio": { "rolloffFactor": 0.5, "volume": 1.0 } } } }, + + "light_30145": { "light": { "power": 120 } }, + + "prop_camera_103001_light": { "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, + "prop_camera_103118_light": { "light": { "shadows": false, "static": false, "dynamic": true, "power": 30 } }, + "prop_camera_103001": { "action": "load", "payload": { "import": "./camera.json" } }, + "prop_camera_103118": { "action": "load", "payload": { "import": "./camera.json" } }, + "func_movelinear_57637": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,8.6,0 ] } } }, + "func_movelinear_82820": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,9.2,0 ] } } }, + "func_movelinear_103114": { "action": "load", "payload": { "import": "./lift.json", "metadata": { "delta": [ 0,-3.0,0 ] } } } + } + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/noise.json b/bin/data2/scene/ss2/noise.json new file mode 100644 index 00000000..446321ad --- /dev/null +++ b/bin/data2/scene/ss2/noise.json @@ -0,0 +1,18 @@ +{ + "name": "Test", + "assets": [], + "behaviors": [ + "RenderBehavior", + "NoiseBehavior" + ], + "transform": { + "position": [ 10, 4, 4 ], + "orientation": [0, 0, 0, 1] + }, + "metadata": { + "size": [ 256, 256, 256 ], + "coefficients": [ 3, 3, 3 ], + "amplitude": 1.5, + "speed": 0.125 + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/player.json b/bin/data2/scene/ss2/player.json new file mode 100644 index 00000000..49c574ca --- /dev/null +++ b/bin/data2/scene/ss2/player.json @@ -0,0 +1,27 @@ +{ + "import": "/player.json", + "assets": [ +// { "filename": "/gui/hud/hud.json", "delay": 0 } + ], + "transform": { + "position": [ 0, 0, 0 ], + "rotation": { + "axis": [ 0, 1, 0 ], + "angle": 3.1415926 + }, + "scale": [ 1, 1, 1 ] + }, + "metadata": { + "overlay": { + "floating": true + }, + "collider": true, + "light": { + "should": false, + "color": [1, 1, 1], + "position": [ 0, 2.5, 0 ], + "power": 1, + "radius": [0.001, 32] + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/scene.json b/bin/data2/scene/ss2/scene.json new file mode 100644 index 00000000..58d81fe4 --- /dev/null +++ b/bin/data2/scene/ss2/scene.json @@ -0,0 +1,55 @@ +{ + "import": "/scene.json", + "assets": [ + { "filename": "./audio/music/medsci1.ogg", "category": "audio-stream", "override": true, "streamed": true }, + "./loading.json" + ], + "system": { + "hot reload": { + "enabled": true + }, + "renderer": { + "clear values": [ + [ 0, 0, 0, 0 ] + ], + "shader": { + "mode": 1, + "scalar": 16, + "parameters": [ 0, 0, 0, "time" ] + } + } + }, + "metadata": { + "menus": { + "pause": "/gui/pause/menu.json" + }, + "bloom": { + "scale": 1.0, + "strength": 0.125, + "sigma": 0.8, + "samples": 5 + }, + "light": { + "exposure": 1.0, + "gamma": 1.0, + "brightnessThreshold": 1.2, + + "ambient": [ 0.0, 0.0, 0.0 ], + + "fog": { + "color": [ 0.025, 0.025, 0.1 ], + "step scale": 0.0, + "range": [ 1, 1 ], + "absorbtion": 0.85, + "density": { + "threshold": 0.5, + "multiplier": 5.0, + "scale": 50.0, + "offset": "time" + } + }, + "should": true, + "shadows": true + } + } +} \ No newline at end of file diff --git a/bin/data2/scene/ss2/scripts/camera.lua b/bin/data2/scene/ss2/scripts/camera.lua new file mode 100644 index 00000000..0cedeea3 --- /dev/null +++ b/bin/data2/scene/ss2/scripts/camera.lua @@ -0,0 +1,191 @@ +local scene = entities.currentScene() +local controller = entities.controller() +local controllerTransform = controller:getComponent("Transform") +local timer = Timer.new() +if not timer:running() then + timer:start(); +end +local metadata = ent:getComponent("Metadata") +local soundEmitter = ent:loadChild("./sound.json",true) +local playSound = function( key ) + if not loop then loop = false end + local url = "./audio/sfx/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = true, + loop = loop, + volume = "sfx", + streamed = true + }, 0) +end +local playSoundscape = function( key ) + local url = "./audio/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = false, + volume = "sfx", + loop = true, + streamed = true + }, 0) +end +local stopSoundscape = function( key ) + local url = "./audio/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end + +local target = Vector3f(0,0,0) +local transform = ent:getComponent("Transform") +local speed = metadata["speed"] or 1.0 / 3.0 +local angle = metadata["angle"] or 1.5 +transform.orientation = Quaternion.axisAngle( Vector3f(0,1,0), 1.5 ) +local starting = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), -angle )) +local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), angle )) +-- on tick +local delta = 0 +local watch = 0 +local alerted = false +local light = nil +local lightOffset = nil + +for k, v in pairs(ent:getChildren()) do + if v:uid() ~= soundEmitter:uid() then + light = v + local transform = v:getComponent("Transform") + lightOffset = Vector3f(transform.position) --:magnitude() + end +end + +ent:bind( "tick", function(self) + soundEmitter:getComponent("Transform").position = transform.position + + local angleThreshold = metadata["sensitivity"] or 20 + + local controllerPosition = Vector3f(controllerTransform.position.x, 0, controllerTransform.position.z) + local cameraPosition = Vector3f(transform.position.x, 0, transform.position.z) + local distance = cameraPosition:distance(controllerPosition) + local direction = cameraPosition - controllerPosition + + local lightTransform = light and light:getComponent("Transform") or nil + local lightMetadata = light and light:getComponent("Metadata") or {} + if lightTransform ~= nil then + lightTransform.position = transform.orientation:rotate( lightOffset ); + if lightMetadata and lightMetadata["light"] and lightMetadata["light"]["static"] then + lightTransform.position = lightTransform.position + transform.position + end + end + + local angle = math.acos(transform.orientation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926 + if angle < angleThreshold and distance < 16 then + if watch == 0 then + watch = 6 + playSound("camera_see") + if light then + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.color", + value = { + [1] = 1, + [2] = 1, + [3] = 0 + } + } ) + end + end + watch = watch + time.delta() + if watch > 12 and not alerted then + playSound("camera_alert") + playSound("xerxes_alert") + playSoundscape("alarm") + alerted = true + timer:reset() + if light then + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.color", + value = { + [1] = 1, + [2] = 0, + [3] = 0 + } + } ) + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade", + value = { + rate = 1, + power = 0.01, + timeout= 0.5 + } + } ) + end + end + else + if watch > 0 and not alerted then + watch = watch - time.delta() + if watch < 0 then + io.print("CAMERA LOST") + watch = 0 + speed = metadata["speed"] or 1.0 / 3.0 + if light then + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.color", + value = { + [1] = 0, + [2] = 1, + [3] = 0 + } + } ) + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade", + value = nil + } ) + end + end + end + end + if not alerted and watch > 0 and light then + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade.rate", + value = math.floor(watch / 2), + } ) + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade.power", + value = 0.01, + } ) + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade.timeout", + value = 0.5, + } ) + end + if alerted and timer:elapsed() >= 60 then + timer:reset() + alerted = false + watch = 0 + io.print("ALERT OVER") + playSound("camera_lost") + stopSoundscape("alarm"); + if light then + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.color", + value = { + [1] = 0, + [2] = 1, + [3] = 0 + } + } ) + light:callHook( "object:UpdateMetadata.%UID%", { + path = "light.fade", + value = nil + } ) + end + end + + delta = delta + time.delta() * speed + local nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 ) + -- stop if we are going to look away from player + local angleNext = math.acos(nextRotation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926 + if watch > 0 and angleNext > angle then + delta = delta - time.delta() * speed * 3 + nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 ) + end + transform.orientation = nextRotation +end ) \ No newline at end of file diff --git a/bin/data2/scene/ss2/scripts/lift.lua b/bin/data2/scene/ss2/scripts/lift.lua new file mode 100644 index 00000000..ae74c00b --- /dev/null +++ b/bin/data2/scene/ss2/scripts/lift.lua @@ -0,0 +1,84 @@ +local scene = entities.currentScene() +local controller = entities.controller() + +local timer = Timer.new() +if not timer:running() then + timer:start(); +end + +local target = Vector3f(0,0,0) +local transform = ent:getComponent("Transform") +local metadata = ent:getComponent("Metadata") +local physics = ent:getComponent("Physics") +local bullet = ent:getComponent("Bullet") +-- local velocty = physics:linearVelocity() +local speed = metadata["speed"] or 1.0 +local starting = transform.position + Vector3f(0,0,0) +local ending = transform.position + Vector3f( metadata["delta"][1], metadata["delta"][2], metadata["delta"][3] ) +local wait = 0 +local direction = 1.0 / math.abs(starting:distance(ending)) +local alpha = 0 +local startingSound = true + +local soundEmitter = ent:loadChild("./sound.json",true) +local playSound = function( key, loop ) + if not loop then loop = false end + local url = "./audio/sfx/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = true, + streamed = true, + volume = "sfx", + loop = loop + }, 0) +end +local stopSound = function( key ) + local url = "./audio/sfx/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end +local playSoundscape = function( key ) + local url = "./audio/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Emit.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]), + spatial = false, + volume = "sfx", + loop = true, + streamed = true + }, 0) +end +local stopSoundscape = function( key ) + local url = "./audio/soundscape/" .. key .. ".ogg" + soundEmitter:queueHook("sound:Stop.%UID%", { + filename = string.resolveURI(url, metadata["system"]["root"]) + }, 0) +end +soundEmitter:getComponent("Transform"):setReference( transform ) +-- on tick +ent:bind( "tick", function(self) + + if wait > 0 then + wait = wait - time.delta() + else + if startingSound then + playSound("lift_start", true) + startingSound = false + end + alpha = alpha + time.delta() * speed * direction + if alpha <= 0 or alpha >= 1 then + alpha = math.clamp( alpha, 0.0, 1.0 ) + direction = -direction + wait = 6 + stopSound("lift_start") + playSound("lift_stop") + startingSound = true + -- bullet:setVelocity( Vector3f(0,0,0) ) + -- physics:setLinearVelocity( Vector3f(0,0,0) ) + else + -- bullet:setVelocity( Vector3f(0,direction,0) ) + -- physics:setLinearVelocity( Vector3f(0,direction / math.abs(direction),0) ) + end + end + transform.position = Vector3f.lerp( starting, ending, alpha ) +end ) \ No newline at end of file diff --git a/bin/data2/scene/ss2/sound.json b/bin/data2/scene/ss2/sound.json new file mode 100644 index 00000000..351f92fe --- /dev/null +++ b/bin/data2/scene/ss2/sound.json @@ -0,0 +1,34 @@ +{ + "type": "Object", + "name": "Sound Emitter", + "ignore": false, + "assets": [ + ], + "behaviors": [ + "SoundEmitterBehavior" + ], + "transform": { + "reference": true + }, + "system": { + "hot reload": { + "enabled": true + }, + "defaults": { + "render": true, + "asset load": true + }, + "load": { + "ignore": true + } + }, + "metadata": { + "audio": { + "spatial": true, + "loop": false, + "volume": 1, + "rolloffFactor": 0.5, + "epsilon": 0.5 + } + } +} \ No newline at end of file diff --git a/bin/dreamcast/config.json b/bin/dreamcast/config.json index 21ef7e2e..bb584cfe 100644 --- a/bin/dreamcast/config.json +++ b/bin/dreamcast/config.json @@ -5,8 +5,8 @@ "meshes": { "interleaved": true }, "matrix": { "reverseInfinite": false }, "lights": { - "max": 8, - "enabled": true + "max": 2, + "enabled": false }, "shadows": { "enabled": false, @@ -74,7 +74,7 @@ } }, "audio": { - "mute": false, + "mute": true, "buffers": { "size": 16384, "count": 3 diff --git a/client/main.cpp b/client/main.cpp index c486936f..069d2132 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -93,9 +93,11 @@ int main(int argc, char** argv){ */ #if UF_ENV_DREAMCAST // UF_TIMER_MULTITRACE_START("Starting"); - ext::render(); - // UF_TIMER_MULTITRACE("render"); ext::tick(); + client::tick(); + // UF_TIMER_MULTITRACE("render"); + ext::render(); + client::render(); // UF_TIMER_MULTITRACE("tick"); // UF_TIMER_MULTITRACE_END("Finished"); #else diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index 15de6ad5..7dc7cbd2 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -29,6 +29,7 @@ namespace ext { uint8_t subpasses = 1; uint8_t samples = 1; uint8_t eyes = 1; + uint8_t views = 1; } metadata; Device* device = VK_NULL_HANDLE; @@ -52,7 +53,7 @@ namespace ext { virtual ext::vulkan::Graphic* getBlitter(size_t = 0); virtual uf::stl::vector getBlitters(); - virtual uf::Image screenshot(size_t = 0); + virtual uf::Image screenshot(size_t = 0, size_t = 0); virtual commands_container_t& getCommands(); virtual commands_container_t& getCommands( std::thread::id ); diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index 41269a61..b3bad72a 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -12,6 +12,7 @@ namespace ext { VkImageUsageFlags usage; bool blend = false; uint8_t samples = 1; + uint8_t layers = 1; bool screenshottable = true; bool aliased = false; } descriptor; diff --git a/engine/inc/uf/ext/vulkan/texture.h b/engine/inc/uf/ext/vulkan/texture.h index 7d2e2cdb..07b85d99 100644 --- a/engine/inc/uf/ext/vulkan/texture.h +++ b/engine/inc/uf/ext/vulkan/texture.h @@ -137,11 +137,15 @@ namespace ext { public: static Texture2D empty; Texture2D(); + + uf::Image screenshot( uint32_t layer = 0 ); }; class UF_API Texture3D : public Texture { public: static Texture3D empty; Texture3D(); + + uf::Image screenshot( uint32_t layer = 0 ); }; class UF_API TextureCube : public Texture { public: diff --git a/engine/inc/uf/ext/xatlas/xatlas.h b/engine/inc/uf/ext/xatlas/xatlas.h index f4dc2ab3..358df8a0 100644 --- a/engine/inc/uf/ext/xatlas/xatlas.h +++ b/engine/inc/uf/ext/xatlas/xatlas.h @@ -5,8 +5,7 @@ #if UF_USE_XATLAS namespace ext { namespace xatlas { - pod::Vector2ui UF_API unwrap( uf::stl::vector& vertices, uf::stl::vector& indices ); - pod::Vector2ui UF_API unwrap( pod::Graph& ); + size_t UF_API unwrap( pod::Graph&, bool = false ); } } #endif \ No newline at end of file diff --git a/engine/inc/uf/macros.h b/engine/inc/uf/macros.h index dd4b479b..ad1d2e26 100644 --- a/engine/inc/uf/macros.h +++ b/engine/inc/uf/macros.h @@ -120,4 +120,11 @@ #define MIN(X, Y) (X) < (Y) ? (X) : (Y) #define MAX(X, Y) (X) > (Y) ? (X) : (Y) #define LENGTH_OF(X) *(&X + 1) - X -#define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i ) \ No newline at end of file +#define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i ) + +#if UF_ENV_DREAMCAST + #define DC_STATS() {\ + UF_MSG_DEBUG(spec::dreamcast::malloc_stats());\ + UF_MSG_DEBUG(spec::dreamcast::pvr_malloc_stats());\ + } +#endif \ No newline at end of file diff --git a/engine/inc/uf/spec/window/dreamcast.h b/engine/inc/uf/spec/window/dreamcast.h index f28b056f..4fc72555 100644 --- a/engine/inc/uf/spec/window/dreamcast.h +++ b/engine/inc/uf/spec/window/dreamcast.h @@ -7,7 +7,12 @@ #if UF_ENV_DREAMCAST namespace spec { namespace dreamcast { - class UF_API Window : public spec::uni::Window { + uf::stl::string malloc_stats( bool = false ); + uf::stl::string pvr_malloc_stats( bool = false ); + + class UF_API Window : public spec::uni::Window { + protected: + spec::dreamcast::Window::context_t* m_context; public: // C-tors UF_API Window(); @@ -48,8 +53,14 @@ namespace spec { void UF_API setTracking(bool state); static pod::Vector2ui UF_API getResolution(); void UF_API toggleFullscreen( bool borderless = false ); + + void UF_API display(); }; } typedef spec::dreamcast::Window Window; } + +namespace uf { + using Window = spec::dreamcast::Window; +} #endif \ No newline at end of file diff --git a/engine/inc/uf/spec/window/universal.h b/engine/inc/uf/spec/window/universal.h index f20de1a5..aa908e18 100644 --- a/engine/inc/uf/spec/window/universal.h +++ b/engine/inc/uf/spec/window/universal.h @@ -13,6 +13,7 @@ namespace spec { class UF_API Window { public: typedef void* handle_t; + typedef void* context_t; typedef uf::String title_t; typedef pod::Vector2i vector_t; @@ -24,6 +25,7 @@ namespace spec { // Window::Events m_events; std::queue m_events; public: + #if 0 // C-tors void create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window" ) {} ;// = 0; // D-tors @@ -48,7 +50,11 @@ namespace spec { bool hasFocus() const;/* = 0;*/ // Update void bufferInputs();/* = 0;*/ - void processEvents();/* = 0;*/ + + static bool isKeyPressed( const uf::stl::string& ); + #endif + #if 0 + void processEvents(); void pushEvent( const uf::Hooks::name_t& name, const uf::stl::string& payload ); void pushEvent( const uf::Hooks::name_t& name, const ext::json::Value& payload ); @@ -58,7 +64,11 @@ namespace spec { template void pushEvent( const uf::Hooks::name_t& name, const T& payload ); bool pollEvents( bool block = false ); - static bool isKeyPressed( const uf::stl::string& ); + #endif + + void pushEvent( const uf::Hooks::name_t& name, const pod::Hook::userdata_t& payload ); + template void pushEvent( const uf::Hooks::name_t& name, const T& payload ); + static bool focused; }; } } diff --git a/engine/inc/uf/spec/window/windows.h b/engine/inc/uf/spec/window/windows.h index abe3865f..4857ede3 100644 --- a/engine/inc/uf/spec/window/windows.h +++ b/engine/inc/uf/spec/window/windows.h @@ -3,15 +3,19 @@ #include #include "universal.h" -#if UF_ENV_WINDOWS #if UF_USE_VULKAN #include +#elif UF_USE_OPENGL #endif + +#if UF_ENV_WINDOWS namespace spec { namespace win32 { class UF_API Window : public spec::uni::Window { public: typedef HWND handle_t; + typedef void* context_t; + /* typedef spec::uni::Window::title_t title_t; typedef spec::uni::Window::vector_t vector_t; @@ -19,6 +23,7 @@ namespace spec { LONG_PTR m_callback; protected: spec::win32::Window::handle_t m_handle; + spec::win32::Window::context_t* m_context; HCURSOR m_cursor; HICON m_icon; @@ -77,8 +82,14 @@ namespace spec { void UF_API_CALL createSurface( VkInstance instance, VkSurfaceKHR& surface ); #endif static uf::stl::string UF_API_CALL getKey(WPARAM key, LPARAM flags); + + void display(); }; } typedef spec::win32::Window Window; } + +namespace uf { + using Window = spec::win32::Window; +} #endif \ No newline at end of file diff --git a/engine/inc/uf/utils/mesh/grid.h b/engine/inc/uf/utils/mesh/grid.h index dc40d7a1..99c64c56 100644 --- a/engine/inc/uf/utils/mesh/grid.h +++ b/engine/inc/uf/utils/mesh/grid.h @@ -80,7 +80,9 @@ namespace uf { uf::meshgrid::cleanup( grid ); + size_t atlasID = 0; for ( auto& pair : grid.nodes ) { auto& node = pair.second; + ++atlasID; for ( auto& pair2 : node.meshlets ) { auto& mlet = pair2.second; if ( mlet.indices.empty() ) continue; @@ -95,8 +97,8 @@ namespace uf { slice.primitive.instance.materialID = meshlet.primitive.instance.materialID; slice.primitive.instance.primitiveID = partitioned.size() - 1; - slice.primitive.instance.meshID = meshlet.primitive.instance.meshID; slice.primitive.instance.objectID = 0; + slice.primitive.instance.auxID = atlasID; slice.primitive.instance.bounds.min = node.effectiveExtents.min; slice.primitive.instance.bounds.max = node.effectiveExtents.max; @@ -105,6 +107,7 @@ namespace uf { slice.primitive.drawCommand.indexID = 0; slice.primitive.drawCommand.vertexID = 0; slice.primitive.drawCommand.instanceID = 0; + slice.primitive.drawCommand.auxID = atlasID; // meshlet.primitive.instance.meshID; slice.primitive.drawCommand.vertices = slice.vertices.size(); } } diff --git a/engine/inc/uf/utils/mesh/mesh.h b/engine/inc/uf/utils/mesh/mesh.h index 9614069b..f023ab68 100644 --- a/engine/inc/uf/utils/mesh/mesh.h +++ b/engine/inc/uf/utils/mesh/mesh.h @@ -48,15 +48,15 @@ namespace ext { namespace pod { struct UF_API DrawCommand { - uint32_t indices = 0; // triangle count - uint32_t instances = 0; // instance count - uint32_t indexID = 0; // starting triangle position - int32_t vertexID = 0; // starting vertex position - uint32_t instanceID = 0; // starting instance position + alignas(4) uint32_t indices = 0; // triangle count + alignas(4) uint32_t instances = 0; // instance count + alignas(4) uint32_t indexID = 0; // starting triangle position + alignas(4) int32_t vertexID = 0; // starting vertex position + alignas(4) uint32_t instanceID = 0; // starting instance position // extra data - uint32_t padding1 = 0; // - uint32_t padding2 = 0; // - uint32_t vertices = 0; // + alignas(4) uint32_t auxID = 0; // + alignas(4) uint32_t materialID = 0; // + alignas(4) uint32_t vertices = 0; // }; @@ -72,7 +72,7 @@ namespace pod { alignas(4) int32_t jointID = -1; alignas(4) int32_t lightmapID = -1; alignas(4) uint32_t imageID = 0; - alignas(4) uint32_t padding3 = 0; + alignas(4) uint32_t auxID = 0; struct Bounds { pod::Vector3f min = { std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; diff --git a/engine/inc/uf/utils/window/window.h b/engine/inc/uf/utils/window/window.h index abe4ffbe..36754b00 100644 --- a/engine/inc/uf/utils/window/window.h +++ b/engine/inc/uf/utils/window/window.h @@ -1,61 +1,4 @@ #pragma once #include -#include -#include - -namespace uf { - class UF_API Window : public spec::uni::Window { - public: - typedef spec::Window window_t; - typedef spec::Context context_t; - protected: - Window::window_t* m_window; - Window::context_t* m_context; - public: - // C-tors - UF_API_CALL Window(); - UF_API_CALL Window( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window", const spec::Context::Settings& settings = spec::Context::Settings() ); - void UF_API_CALL create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title = L"Window", const spec::Context::Settings& settings = spec::Context::Settings() ); - // D-tors - ~Window(); - void UF_API_CALL terminate(); - // Gets - spec::uni::Window::vector_t UF_API_CALL getPosition() const; - spec::uni::Window::vector_t UF_API_CALL getSize() const; - size_t UF_API_CALL getRefreshRate() const; - // Attribute modifiers - void UF_API_CALL setPosition( const spec::uni::Window::vector_t& position ); - void UF_API_CALL centerWindow(); - void UF_API_CALL setMousePosition( const spec::uni::Window::vector_t& position ); - spec::uni::Window::vector_t UF_API_CALL getMousePosition(); - void UF_API_CALL setSize( const spec::uni::Window::vector_t& size ); - void UF_API_CALL setTitle( const spec::uni::Window::title_t& title ); - void UF_API_CALL setIcon( const spec::uni::Window::vector_t& size, uint8_t* pixels ); - void UF_API_CALL setVisible( bool visibility ); - void UF_API_CALL setCursorVisible( bool visibility ); - void UF_API_CALL setKeyRepeatEnabled( bool state ); - void UF_API_CALL setMouseGrabbed( bool state ); - - void UF_API_CALL requestFocus(); - bool UF_API_CALL hasFocus() const; - static pod::Vector2ui UF_API_CALL getResolution(); - void UF_API_CALL toggleFullscreen( bool borderless = false ); - - #if defined(UF_USE_VULKAN) && UF_USE_VULKAN == 1 - uf::stl::vector getExtensions( bool validationEnabled = true ); - void createSurface( VkInstance instance, VkSurfaceKHR& surface ); - #endif - - static bool focused; - static bool UF_API_CALL isKeyPressed(const uf::stl::string&); - - void UF_API_CALL bufferInputs(); - void UF_API_CALL processEvents(); - bool UF_API_CALL pollEvents(bool block = false); - bool UF_API_CALL setActive( bool active = true ); - void UF_API_CALL display(); - Window::window_t* UF_API_CALL getHandle(); - const Window::window_t* UF_API_CALL getHandle() const; - }; -} \ No newline at end of file +#include \ No newline at end of file diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index 6d7b2945..56ff080f 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -142,6 +142,7 @@ namespace { instance.materialID = json["materialID"].as( instance.materialID ); instance.primitiveID = json["primitiveID"].as( instance.primitiveID ); instance.meshID = json["meshID"].as( instance.meshID ); + instance.auxID = json["auxID"].as( instance.auxID ); instance.objectID = json["objectID"].as( instance.objectID ); instance.bounds.min = uf::vector::decode( json["bounds"]["min"], instance.bounds.min ); instance.bounds.max = uf::vector::decode( json["bounds"]["max"], instance.bounds.max ); @@ -155,8 +156,8 @@ namespace { drawCommand.indexID = json["indexID"].as( drawCommand.indexID ); drawCommand.vertexID = json["vertexID"].as( drawCommand.vertexID ); drawCommand.instanceID = json["instanceID"].as( drawCommand.instanceID ); - // drawCommand.padding1 = json["padding1"].as( drawCommand.padding1 ); - // drawCommand.padding2 = json["padding2"].as( drawCommand.padding2 ); + drawCommand.auxID = json["auxID"].as( drawCommand.auxID ); + drawCommand.materialID = json["materialID"].as( drawCommand.materialID ); drawCommand.vertices = json["vertices"].as( drawCommand.vertices ); return drawCommand; } @@ -225,12 +226,14 @@ namespace { // remove extraneous buffers #if UF_USE_OPENGL + /* for ( auto& attribute : mesh.vertex.attributes ) { if ( attribute.descriptor.name == "position" ) continue; if ( attribute.descriptor.name == "color" ) continue; if ( attribute.descriptor.name == "uv" ) continue; if ( attribute.descriptor.name == "st" ) continue; } + */ #endif mesh.updateDescriptor(); @@ -293,6 +296,7 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize auto name = value["name"].as(); /*graph.storage*/uf::graph::storage.instances[name] = decodeInstance( value, graph ); graph.instances.emplace_back(name); + UF_MSG_DEBUG( name ); }); }); jobs.emplace_back([&]{ @@ -436,5 +440,10 @@ pod::Graph uf::graph::load( const uf::stl::string& filename, const uf::Serialize } } UF_DEBUG_TIMER_MULTITRACE_END("Processing graph..."); + +#if UF_ENV_DREAMCAST + DC_STATS(); +#endif + return graph; } \ No newline at end of file diff --git a/engine/src/engine/graph/encode.cpp b/engine/src/engine/graph/encode.cpp index 3cc405d6..c3bb8633 100644 --- a/engine/src/engine/graph/encode.cpp +++ b/engine/src/engine/graph/encode.cpp @@ -118,6 +118,7 @@ namespace { json["materialID"] = instance.materialID; json["primitiveID"] = instance.primitiveID; json["meshID"] = instance.meshID; + json["auxID"] = instance.auxID; json["objectID"] = instance.objectID; json["bounds"]["min"] = uf::vector::encode( instance.bounds.min, settings ); @@ -132,8 +133,8 @@ namespace { json["indexID"] = drawCommand.indexID; json["vertexID"] = drawCommand.vertexID; json["instanceID"] = drawCommand.instanceID; - // json["padding1"] = drawCommand.padding1; - // json["padding2"] = drawCommand.padding2; + json["auxID"] = drawCommand.auxID; + json["materialID"] = drawCommand.materialID; json["vertices"] = drawCommand.vertices; return json; } @@ -237,11 +238,13 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename ) }; if ( !settings.combined ) uf::io::mkdir(directory); #if UF_USE_XATLAS +/* if ( settings.unwrap ) { pod::Graph& g = const_cast(graph); auto size = ext::xatlas::unwrap( g ); serializer["wrapped"] = uf::vector::encode( size ); } +*/ #endif pod::Thread::container_t jobs; @@ -426,11 +429,12 @@ void uf::graph::save( const pod::Graph& graph, const uf::stl::string& filename ) #if UF_GRAPH_LOAD_MULTITHREAD if ( !jobs.empty() ) uf::thread::batchWorkers( jobs ); #else - for ( auto& job : jobs ) return job(); + for ( auto& job : jobs ) job(); #endif if ( !settings.combined ) target = directory + "/graph.json"; serializer.writeToFile( target, settings ); + UF_MSG_DEBUG("Saving graph to `" << target << "`"); } uf::stl::string uf::graph::print( const pod::Graph& graph ) { diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 55afe00d..0c0660fd 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -10,12 +10,6 @@ #include #include -#if UF_ENV_DREAMCAST - #define UF_GRAPH_LOAD_MULTITHREAD 1 -#else - #define UF_GRAPH_LOAD_MULTITHREAD 1 -#endif - namespace { bool newGraphAdded = true; } @@ -144,11 +138,18 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) { graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT); graphic.material.metadata.autoInitializeUniforms = true; } + + uf::renderer::Buffer* indirect = NULL; + for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer; + { auto& shader = graphic.material.getShader("vertex"); shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera ); - // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands ); + // // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands ); + #if UF_USE_VULKAN + shader.buffers.emplace_back().aliasBuffer( *indirect ); + #endif shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance ); shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint ); #if UF_USE_VULKAN @@ -204,7 +205,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) { auto& shader = graphic.material.getShader("compute", "culling"); shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera ); + #if UF_USE_VULKAN shader.buffers.emplace_back().aliasBuffer( *indirect ); + #endif shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance ); } } @@ -299,8 +302,10 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) { { graphic.material.metadata.autoInitializeUniforms = false; uf::stl::string vertexShaderFilename = uf::io::resolveURI("/graph/baking/bake.vert.spv"); + uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/bake.geom.spv"); uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/bake.frag.spv"); graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking"); + graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking"); graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking"); graphic.material.metadata.autoInitializeUniforms = true; } @@ -316,9 +321,13 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) { // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera ); // shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands ); + #if UF_USE_VULKAN + shader.buffers.emplace_back().aliasBuffer( *indirect ); + #endif shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance ); shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint ); } + { size_t maxTextures = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as(512); size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as(128); @@ -360,15 +369,65 @@ void uf::graph::process( pod::Graph& graph ) { // process lightmap #if UF_USE_OPENGL - #if UF_ENV_DREAMCAST - #define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.min.png" - #else - #define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.png" - #endif + #define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.min.dtex" #else - #define UF_GRAPH_DEFAULT_LIGHTMAP "" + #define UF_GRAPH_DEFAULT_LIGHTMAP "./lightmap.%i.png" #endif - { + if ( graph.metadata["lightmap"].as() ) { + uf::stl::unordered_map filenames; + uf::stl::unordered_map lightmapIDs; + + UF_MSG_DEBUG( graph.instances.size() ); + + for ( auto& name : graph.instances ) { + auto& instance = uf::graph::storage.instances[name]; + // if ( !instance.auxID ) break; + filenames[instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(instance.auxID)); + } + for ( auto& name : graph.primitives ) { + auto& primitives = uf::graph::storage.primitives[name]; + for ( auto& primitive : primitives ) { + // if ( !primitive.instance.auxID ) break; + filenames[primitive.instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(primitive.instance.auxID)); + } + } + for ( auto& pair : filenames ) { + auto i = pair.first; + auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) ); + + if ( !uf::io::exists( f ) ) { + UF_MSG_ERROR( "lightmap does not exist: " << f ) + continue; + } + + auto textureID = graph.textures.size(); + auto imageID = graph.images.size(); + + auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)]; + auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)]; + image.open( f, false ); + + texture.index = imageID; + + lightmapIDs[i] = textureID; + + graph.metadata["lightmaps"][i] = f; + graph.metadata["baking"]["enabled"] = false; + } + + for ( auto& name : graph.instances ) { + auto& instance = uf::graph::storage.instances[name]; + if ( lightmapIDs.count( instance.auxID ) == 0 ) continue; + instance.lightmapID = lightmapIDs[instance.auxID]; + } + for ( auto& name : graph.primitives ) { + auto& primitives = uf::graph::storage.primitives[name]; + for ( auto& primitive : primitives ) { + if ( lightmapIDs.count( primitive.instance.auxID ) == 0 ) continue; + primitive.instance.lightmapID = lightmapIDs[primitive.instance.auxID]; + } + } + #if 0 const uf::stl::string lightmapFilename = graph.metadata["lightmap"].as(UF_GRAPH_DEFAULT_LIGHTMAP); // load lightmap, if requested if ( lightmapFilename != "" ) { @@ -399,6 +458,7 @@ void uf::graph::process( pod::Graph& graph ) { graph.metadata["baking"]["enabled"] = false; } } + #endif } // add atlas @@ -430,6 +490,7 @@ void uf::graph::process( pod::Graph& graph ) { if ( !texture.generated() ) { bool isLightmap = graph.metadata["lightmapped"].as() == key; auto filter = graph.metadata["filter"].as() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR; + // auto filter = uf::renderer::enums::Filter::LINEAR; texture.sampler.descriptor.filter.min = filter; texture.sampler.descriptor.filter.mag = filter; @@ -585,8 +646,8 @@ void uf::graph::process( pod::Graph& graph ) { mesh.insertInstances( m ); // mesh.insertIndirects( m ); - pod::DrawCommand* dc = (pod::DrawCommand*) m.getBuffer( m.indirect ).data(); - for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( dc[i] ); + pod::DrawCommand* drawCommand = (pod::DrawCommand*) m.getBuffer( m.indirect ).data(); + for ( size_t i = 0; i < m.indirect.count; ++i ) drawCommands.emplace_back( drawCommand[i] ); } // fix up draw command for combined mesh @@ -641,32 +702,44 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) auto& metadataJson = entity.getComponent(); metadataJson["system"]["graph"]["name"] = node.name; metadataJson["system"]["graph"]["index"] = index; + // on systems where frametime is very, very important, we can set all static nodes to not tick + // tie to tag - if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) { - auto& info = graph.metadata["tags"][node.name]; - if ( info["ignore"].as() ) { - return; + { + ext::json::Value info = ext::json::null(); + if ( ext::json::isObject( graph.metadata["tags"][node.name] ) ) { + info = graph.metadata["tags"][node.name]; + } else { + ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) { + if ( !uf::string::isRegex( key ) ) return; + if ( uf::string::matches( node.name, key ).empty() ) return; + info = value; + }); } - if ( info["action"].as() == "load" ) { - if ( info["filename"].is() ) { + if ( ext::json::isObject( info ) ) { + if ( info["ignore"].as() ) return; + + if ( info["action"].as() == "load" ) { + if ( info["filename"].is() ) { + uf::stl::string filename = uf::io::resolveURI( info["filename"].as(), graph.metadata["root"].as() ); + entity.load(filename); + } else if ( ext::json::isObject( info["payload"] ) ) { + uf::Serializer json = info["payload"]; + json["root"] = graph.metadata["root"]; + entity.load(json); + } + } else if ( info["action"].as() == "attach" ) { uf::stl::string filename = uf::io::resolveURI( info["filename"].as(), graph.metadata["root"].as() ); - entity.load(filename); - } else if ( ext::json::isObject( info["payload"] ) ) { - uf::Serializer json = info["payload"]; - json["root"] = graph.metadata["root"]; - entity.load(json); + auto& child = entity.loadChild( filename, false ); + auto& childTransform = child.getComponent>(); + auto flatten = uf::transform::flatten( node.transform ); + if ( !info["preserve position"].as() ) childTransform.position = flatten.position; + if ( !info["preserve orientation"].as() ) childTransform.orientation = flatten.orientation; + } + if ( info["static"].is() ) { + metadata.system.ignoreGraph = info["static"].as(); } - } else if ( info["action"].as() == "attach" ) { - uf::stl::string filename = uf::io::resolveURI( info["filename"].as(), graph.metadata["root"].as() ); - auto& child = entity.loadChild( filename, false ); - auto& childTransform = child.getComponent>(); - auto flatten = uf::transform::flatten( node.transform ); - if ( !info["preserve position"].as() ) childTransform.position = flatten.position; - if ( !info["preserve orientation"].as() ) childTransform.orientation = flatten.orientation; - } - if ( info["static"].is() ) { - metadata.system.ignoreGraph = info["static"].as(); } } // create as light @@ -1014,7 +1087,7 @@ void uf::graph::destroy( pod::Graph& graph ) { #endif uf::graph::storage.buffers.camera.destroy(); -// uf::graph::storage.buffers.drawCommands.destroy(); + uf::graph::storage.buffers.drawCommands.destroy(); uf::graph::storage.buffers.instance.destroy(); uf::graph::storage.buffers.joint.destroy(); uf::graph::storage.buffers.material.destroy(); @@ -1029,7 +1102,7 @@ void uf::graph::initialize() { const size_t MAX_SIZE = 1024; #endif uf::graph::storage.buffers.camera.initialize( (const void*) nullptr, sizeof(pod::Camera::Viewports), uf::renderer::enums::Buffer::UNIFORM ); -// uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); + uf::graph::storage.buffers.drawCommands.initialize( (const void*) nullptr, sizeof(pod::DrawCommand) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); uf::graph::storage.buffers.instance.initialize( (const void*) nullptr, sizeof(pod::Instance) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); uf::graph::storage.buffers.joint.initialize( (const void*) nullptr, sizeof(pod::Matrix4f) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); uf::graph::storage.buffers.material.initialize( (const void*) nullptr, sizeof(pod::Material) * MAX_SIZE, uf::renderer::enums::Buffer::STORAGE ); @@ -1073,7 +1146,7 @@ void uf::graph::tick() { } for ( auto pair : textureOrderedMap ) textures.emplace_back( uf::graph::storage.textures.map[pair.second] ); #endif - // uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ); + uf::graph::storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ); uf::graph::storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ); uf::graph::storage.buffers.texture.update( (const void*) textures.data(), textures.size() * sizeof(pod::Texture) ); ::newGraphAdded = false; diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index b8796c77..901d85db 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -19,6 +19,9 @@ #include #include +#if UF_USE_XATLAS + #include +#endif namespace { decltype(auto) getWrapMode(int32_t wrapMode) { @@ -500,8 +503,18 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize texture.index = atlasImageIndex; } } + // generate STs +#if UF_USE_XATLAS + { + UF_MSG_DEBUG( "Generating ST's..." ); + size_t atlases = ext::xatlas::unwrap( graph ); + UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" ); + } +#endif - if ( graph.metadata["exporter"]["enabled"].as() ) uf::graph::save( graph, filename ); + if ( graph.metadata["exporter"]["enabled"].as() ) { + uf::graph::save( graph, filename ); + } return graph; } #endif \ No newline at end of file diff --git a/engine/src/ext/gltf/processPrimitives2.inl b/engine/src/ext/gltf/processPrimitives2.inl index bcbd60fd..af1fe4c6 100644 --- a/engine/src/ext/gltf/processPrimitives2.inl +++ b/engine/src/ext/gltf/processPrimitives2.inl @@ -171,7 +171,9 @@ for ( auto& p : m.primitives ) { if ( meshgrid.grid.divisions.x > 1 && meshgrid.grid.divisions.y > 1 && meshgrid.grid.divisions.z > 1 ) { auto partitioned = uf::meshgrid::partition( meshgrid.grid, meshlets, meshgrid.eps ); - if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: " << m.name << ": " << meshlets.size() << " -> " << partitioned.size() ); + if ( meshgrid.print ) UF_MSG_DEBUG( "Draw commands: " << m.name << ": " << meshlets.size() << " -> " << partitioned.size() << " | Partitions: " << + (meshgrid.grid.divisions.x * meshgrid.grid.divisions.y * meshgrid.grid.divisions.z) << " -> " << meshgrid.grid.nodes.size() + ); meshlets = std::move( partitioned ); } @@ -183,16 +185,17 @@ if ( meshgrid.grid.divisions.x > 1 && meshgrid.grid.divisions.y > 1 && meshgrid. mesh.bind(); for ( auto& meshlet : meshlets ) { - drawCommands.emplace_back(pod::DrawCommand{ + auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ .indices = meshlet.indices.size(), .instances = 1, .indexID = indexID, .vertexID = vertexID, .instanceID = 0, - - + .auxID = meshlet.primitive.drawCommand.auxID, + .materialID = meshlet.primitive.drawCommand.materialID, .vertices = meshlet.vertices.size(), }); + //UF_MSG_DEBUG( ); primitives.emplace_back( meshlet.primitive ); diff --git a/engine/src/ext/opengl/commands.cpp b/engine/src/ext/opengl/commands.cpp index 79cbfc7c..9886411d 100644 --- a/engine/src/ext/opengl/commands.cpp +++ b/engine/src/ext/opengl/commands.cpp @@ -295,10 +295,11 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: GL_ERROR_CHECK(glEnable(drawInfo.textures.primary.viewType)); GL_ERROR_CHECK(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); GL_ERROR_CHECK(glBindTexture(drawInfo.textures.primary.viewType, drawInfo.textures.primary.image)); - GL_ERROR_CHECK(glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); 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 ) { + 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; diff --git a/engine/src/ext/opengl/device.cpp b/engine/src/ext/opengl/device.cpp index adba51ee..f469faa9 100644 --- a/engine/src/ext/opengl/device.cpp +++ b/engine/src/ext/opengl/device.cpp @@ -137,7 +137,7 @@ spec::Context& ext::opengl::Device::activateContext( std::thread::id id ) { bool exists = this->contexts.has(id); auto& context = this->contexts.get(id); if ( !exists ) { - context = (spec::Context*) spec::uni::Context::create( contextSettings, *this->window->getHandle() ); + context = (spec::Context*) spec::uni::Context::create( contextSettings, *this->window ); } context->setActive(true); return *context; diff --git a/engine/src/ext/opengl/rendermodes/base.cpp b/engine/src/ext/opengl/rendermodes/base.cpp index c80b81c7..0501948b 100644 --- a/engine/src/ext/opengl/rendermodes/base.cpp +++ b/engine/src/ext/opengl/rendermodes/base.cpp @@ -74,7 +74,8 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) { 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)); // GL_ERROR_CHECK(glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)); diff --git a/engine/src/ext/opengl/texture.cpp b/engine/src/ext/opengl/texture.cpp index 8a3e11c0..fe277454 100644 --- a/engine/src/ext/opengl/texture.cpp +++ b/engine/src/ext/opengl/texture.cpp @@ -210,13 +210,25 @@ void ext::opengl::Texture::fromBuffers( this->initialize(device, viewType, texWidth, texHeight, texDepth, layers); this->format = format; -#if !UF_ENV_DREAMCAST +#if UF_ENV_DREAMCAST + if ( internalFormat > 0 ) { + this->mips = 0; + } +#endif + if ( this->mips == 0 ) { this->mips = 1; } else if ( this->depth == 1 ) { this->mips = static_cast(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1; } -#endif + + if ( this->mips > 1 ) { + switch ( sampler.descriptor.filter.min ) { + case GL_LINEAR: sampler.descriptor.filter.min = GL_LINEAR_MIPMAP_LINEAR; break; + case GL_NEAREST: sampler.descriptor.filter.min = GL_NEAREST_MIPMAP_NEAREST; break; + } + } + // Create sampler sampler.descriptor.mip.min = 0; sampler.descriptor.mip.max = static_cast(this->mips); @@ -267,6 +279,7 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer GL_MUTEX_LOCK(); GL_ERROR_CHECK(glBindTexture(viewType, image)); GL_ERROR_CHECK(glCompressedTexImage2DARB( viewType, 0, internalFormat, width, height, 0, bufferSize, data)); + if ( this->mips > 1 ) GL_ERROR_CHECK(glGenerateMipmapEXT(GL_TEXTURE_2D)); GL_ERROR_CHECK(glBindTexture(viewType, 0)); GL_MUTEX_UNLOCK(); return; @@ -305,6 +318,7 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer case enums::Image::VIEW_TYPE_3D: { GL_ERROR_CHECK(glTexImage3D(viewType, 0, format, width, height, depth, 0, format, type, data)); } break; #endif } + if ( this->mips > 1 ) GL_ERROR_CHECK(glGenerateMipmapEXT(GL_TEXTURE_2D)); GL_ERROR_CHECK(glBindTexture(viewType, 0)); GL_MUTEX_UNLOCK(); } diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index 3cedc86f..2b13c0b0 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -760,6 +760,7 @@ void ext::vulkan::Device::initialize() { VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{}; VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures{}; VkPhysicalDeviceShaderDrawParametersFeatures shaderDrawParametersFeatures{}; + VkPhysicalDeviceRobustness2FeaturesEXT robustnessFeatures{}; { deviceCreateInfo.pEnabledFeatures = nullptr; deviceCreateInfo.pNext = &physicalDeviceFeatures2; @@ -780,6 +781,11 @@ void ext::vulkan::Device::initialize() { { shaderDrawParametersFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; shaderDrawParametersFeatures.shaderDrawParameters = VK_TRUE; + shaderDrawParametersFeatures.pNext = &robustnessFeatures; + } + { + robustnessFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + robustnessFeatures.nullDescriptor = VK_TRUE; } if ( vkCreateDevice( this->physicalDevice, &deviceCreateInfo, nullptr, &this->logicalDevice) != VK_SUCCESS ) { diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index c183303d..4aa6009e 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -364,6 +364,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip uf::stl::vector image; uf::stl::vector image2D; + uf::stl::vector image2DA; uf::stl::vector imageCube; uf::stl::vector image3D; uf::stl::vector imageUnknown; @@ -393,6 +394,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip infos.image.emplace_back(texture.descriptor); switch ( texture.viewType ) { case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: infos.image2DA.emplace_back(texture.descriptor); break; case VK_IMAGE_VIEW_TYPE_CUBE: infos.imageCube.emplace_back(texture.descriptor); break; case VK_IMAGE_VIEW_TYPE_3D: infos.image3D.emplace_back(texture.descriptor); break; default: infos.imageUnknown.emplace_back(texture.descriptor); break; @@ -424,6 +426,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip } size_t maxTextures2D = 0; + size_t maxTextures2DA = 0; size_t maxTextures3D = 0; size_t maxTexturesCube = 0; size_t maxTexturesUnknown = 0; @@ -431,10 +434,12 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip if ( type == ext::vulkan::enums::Image::VIEW_TYPE_3D ) ++maxTextures3D; else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) ++maxTexturesCube; else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D ) ++maxTextures2D; + else if ( type == ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY ) ++maxTextures2DA; else ++maxTexturesUnknown; } while ( infos.image2D.size() < maxTextures2D ) infos.image2D.emplace_back(Texture2D::empty.descriptor); + while ( infos.image2DA.size() < maxTextures2DA ) infos.image2DA.emplace_back(Texture2D::empty.descriptor); while ( infos.imageCube.size() < maxTexturesCube ) infos.imageCube.emplace_back(TextureCube::empty.descriptor); while ( infos.image3D.size() < maxTextures3D ) infos.image3D.emplace_back(Texture3D::empty.descriptor); while ( infos.imageUnknown.size() < maxTexturesUnknown ) infos.imageUnknown.emplace_back(Texture2D::empty.descriptor); @@ -452,6 +457,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip auto imageInfo = infos.image.begin(); auto image2DInfo = infos.image2D.begin(); + auto image2DAInfo = infos.image2DA.begin(); auto imageCubeInfo = infos.imageCube.begin(); auto image3DInfo = infos.image3D.begin(); auto imageUnknownInfo = infos.imageUnknown.begin(); @@ -476,6 +482,16 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip layout.descriptorCount )); image2DInfo += layout.descriptorCount; + } else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY ) { + UF_ASSERT_BREAK_MSG( image2DAInfo != infos.image2DA.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount ) + writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet( + descriptorSet, + layout.descriptorType, + layout.binding, + &(*image2DAInfo), + layout.descriptorCount + )); + image2DAInfo += layout.descriptorCount; } else if ( imageType == ext::vulkan::enums::Image::VIEW_TYPE_CUBE ) { UF_ASSERT_BREAK_MSG( imageCubeInfo != infos.imageCube.end(), "Filename: " << shader->filename << "\tCount: " << layout.descriptorCount ) writeDescriptorSets.emplace_back(ext::vulkan::initializers::writeDescriptorSet( diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index 6b4eac66..98ce4527 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -41,10 +41,10 @@ uf::stl::vector ext::vulkan::RenderMode::getBlitters() { return {}; } -uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { +uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layerID ) { uf::Image image; - if ( !device || renderTarget.attachments.size() < i ) return image; - auto& attachment = renderTarget.attachments[i]; + if ( !device || renderTarget.attachments.size() < attachmentID ) return image; + auto& attachment = renderTarget.attachments[attachmentID]; bool blitting = true; VkFormatProperties formatProperties; @@ -92,6 +92,7 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); imageMemoryBarrier.image = attachment.image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID; imageMemoryBarrier.oldLayout = attachment.descriptor.layout; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); @@ -104,9 +105,11 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { VkImageResolve imageResolveRegion{}; imageResolveRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageResolveRegion.srcSubresource.baseArrayLayer = layerID; imageResolveRegion.srcSubresource.layerCount = 1; // imageResolveRegion.srcOffsets[1] = blitSize; imageResolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageResolveRegion.dstSubresource.baseArrayLayer = 0; imageResolveRegion.dstSubresource.layerCount = 1; // imageResolveRegion.dstOffsets[1] = blitSize; imageResolveRegion.extent = { renderTarget.width, renderTarget.height, 1 }; @@ -120,9 +123,11 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { VkImageBlit imageBlit{}; imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.srcSubresource.baseArrayLayer = layerID; imageBlit.srcSubresource.layerCount = 1; imageBlit.srcOffsets[1] = blitSize; imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.dstSubresource.baseArrayLayer = 0; imageBlit.dstSubresource.layerCount = 1; imageBlit.dstOffsets[1] = blitSize; @@ -130,8 +135,10 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { } else { VkImageCopy imageCopy{}; imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.srcSubresource.baseArrayLayer = layerID; imageCopy.srcSubresource.layerCount = 1; imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.dstSubresource.baseArrayLayer = 0; imageCopy.dstSubresource.layerCount = 1; imageCopy.extent = { renderTarget.width, renderTarget.height, 1 }; @@ -141,11 +148,13 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t i ) { imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; imageMemoryBarrier.image = temporary; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); imageMemoryBarrier.image = attachment.image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; imageMemoryBarrier.newLayout = attachment.descriptor.layout; vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 40310bb4..4bf5f54f 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -61,6 +61,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { uint8_t msaa = ext::vulkan::sampleCount(metadata.samples); if ( metadata.subpasses == 0 ) metadata.subpasses = 1; renderTarget.device = &device; + renderTarget.views = metadata.views; if ( metadata.type == "depth" || metadata.type == "vxgi" ) { renderTarget.views = metadata.subpasses; struct { diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index a21db0fb..2fc7f5d6 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -100,7 +100,10 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript } VkImageViewCreateInfo imageView = {}; imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D; + imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + if ( this->views > 1 ) { + imageView.viewType = this->views == 6 ? VK_IMAGE_VIEW_TYPE_CUBE : VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } imageView.format = attachment->descriptor.format; imageView.subresourceRange = {}; imageView.subresourceRange.aspectMask = aspectMask; diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index ada879a1..272489f2 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -85,6 +85,18 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig this->layers = layers; // implicitly set type + if ( width > 1 && height == 1 && depth == 1 ) { + this->type = ext::vulkan::enums::Image::TYPE_1D; + this->viewType = layers == 1 ? ext::vulkan::enums::Image::VIEW_TYPE_1D : ext::vulkan::enums::Image::VIEW_TYPE_1D_ARRAY; + } else if ( height > 1 && depth == 1 ) { + this->type = ext::vulkan::enums::Image::TYPE_2D; + this->viewType = layers == 1 ? ext::vulkan::enums::Image::VIEW_TYPE_2D : ext::vulkan::enums::Image::VIEW_TYPE_2D_ARRAY; + if ( layers == 6 ) this->viewType = ext::vulkan::enums::Image::VIEW_TYPE_CUBE; + } else { + this->type = ext::vulkan::enums::Image::TYPE_3D; + this->viewType = layers == 6 ? ext::vulkan::enums::Image::VIEW_TYPE_CUBE_ARRAY : ext::vulkan::enums::Image::VIEW_TYPE_3D; + } +/* if ( width > 1 && height > 1 && depth > 1 ) { this->type = ext::vulkan::enums::Image::TYPE_3D; } else if ( (width == 1 && height > 1 && depth > 1) || (width > 1 && height == 1 && depth > 1) || (width > 1 && height > 1 && depth == 1) ) { @@ -92,6 +104,7 @@ void ext::vulkan::Texture::initialize( Device& device, size_t width, size_t heig } else if ( (width > 1 && height == 1 && depth == 1) || (width == 1 && height > 1 && depth == 1) || (width == 1 && height == 1 && depth > 1) ) { this->type = ext::vulkan::enums::Image::TYPE_1D; } +*/ /* if ( layers > 1 ) { if ( viewType == ext::vulkan::enums::Image::VIEW_TYPE_1D ) viewType = ext::vulkan::enums::Image::VIEW_TYPE_1D_ARRAY; @@ -818,6 +831,227 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3 } } +uf::Image ext::vulkan::Texture2D::screenshot( uint32_t layerID ) { + uf::Image image; + if ( !device ) return image; + + bool blitting = true; + VkFormatProperties formatProperties; + vkGetPhysicalDeviceFormatProperties(device->physicalDevice, this->format, &formatProperties); + if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) blitting = false; + vkGetPhysicalDeviceFormatProperties(device->physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties); + if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) blitting = false; + + VkImage temporary; + VkImageCreateInfo imageCreateInfo = {}; + imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + imageCreateInfo.extent = { this->width, this->height, 1 }; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VmaAllocation allocation; + VmaAllocationInfo allocationInfo; + VmaAllocationCreateInfo allocationCreateInfo = {}; + allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo)); + VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory; + + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + imageMemoryBarrier.image = temporary; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + imageMemoryBarrier.image = this->image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID; + imageMemoryBarrier.oldLayout = descriptor.imageLayout; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + if ( blitting ) { + VkOffset3D blitSize; + blitSize.x = this->width; + blitSize.y = this->height; + blitSize.z = 1; + + VkImageBlit imageBlit{}; + imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.srcSubresource.baseArrayLayer = layerID; + imageBlit.srcSubresource.layerCount = 1; + imageBlit.srcOffsets[1] = blitSize; + imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.dstSubresource.baseArrayLayer = 0; + imageBlit.dstSubresource.layerCount = 1; + imageBlit.dstOffsets[1] = blitSize; + + vkCmdBlitImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST); + } else { + VkImageCopy imageCopy{}; + imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.srcSubresource.baseArrayLayer = layerID; + imageCopy.srcSubresource.layerCount = 1; + imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.dstSubresource.baseArrayLayer = 0; + imageCopy.dstSubresource.layerCount = 1; + imageCopy.extent = { this->width, this->height, 1 }; + + vkCmdCopyImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy ); + } + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + + imageMemoryBarrier.image = temporary; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + imageMemoryBarrier.image = this->image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = layerID; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + imageMemoryBarrier.newLayout = descriptor.imageLayout; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + device->flushCommandBuffer(copyCmd, true); + + const uint8_t* data; + vmaMapMemory( allocator, allocation, (void**)&data ); + image.loadFromBuffer( data, {this->width, this->height}, 8, 4, false ); + vmaUnmapMemory( allocator, allocation ); + vmaDestroyImage(allocator, temporary, allocation); + return image; +} + +uf::Image ext::vulkan::Texture3D::screenshot( uint32_t layerID ) { + uf::Image image; + if ( !device ) return image; + + bool blitting = true; + VkFormatProperties formatProperties; + vkGetPhysicalDeviceFormatProperties(device->physicalDevice, this->format, &formatProperties); + if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) blitting = false; + vkGetPhysicalDeviceFormatProperties(device->physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties); + if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) blitting = false; + + VkImage temporary; + VkImageCreateInfo imageCreateInfo = {}; + imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; + imageCreateInfo.extent = { this->width, this->height, 1 }; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VmaAllocation allocation; + VmaAllocationInfo allocationInfo; + VmaAllocationCreateInfo allocationCreateInfo = {}; + allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocationCreateInfo, &temporary, &allocation, &allocationInfo)); + VkDeviceMemory temporaryMemory = allocationInfo.deviceMemory; + + VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true); + + VkImageMemoryBarrier imageMemoryBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // ext::vulkan::device.queueFamilyIndices.graphics; //VK_QUEUE_FAMILY_IGNORED + imageMemoryBarrier.subresourceRange.baseMipLevel = 0; + imageMemoryBarrier.subresourceRange.levelCount = 1; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.subresourceRange.layerCount = 1; + imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + imageMemoryBarrier.image = temporary; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + imageMemoryBarrier.image = this->image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.oldLayout = descriptor.imageLayout; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + if ( blitting ) { + VkOffset3D blitSize; + blitSize.x = this->width; + blitSize.y = this->height; + blitSize.z = 1; + + VkImageBlit imageBlit{}; + imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.srcSubresource.baseArrayLayer = 0; + imageBlit.srcSubresource.layerCount = 1; + imageBlit.srcOffsets[0] = { 0, 0, layerID }; + imageBlit.srcOffsets[1] = { this->width, this->height, layerID + 1 }; + imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBlit.dstSubresource.baseArrayLayer = 0; + imageBlit.dstSubresource.layerCount = 1; + imageBlit.dstOffsets[0] = { 0, 0, 0 }; + imageBlit.dstOffsets[1] = { this->width, this->height, 1 }; + + vkCmdBlitImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST); + } else { + VkImageCopy imageCopy{}; + imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.srcSubresource.baseArrayLayer = 0; + imageCopy.srcSubresource.layerCount = 1; + imageCopy.srcOffset = { 0, 0, layerID }; + + imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageCopy.dstSubresource.baseArrayLayer = 0; + imageCopy.dstSubresource.layerCount = 1; + imageCopy.dstOffset = { 0, 0, 0 }; + imageCopy.extent = { this->width, this->height, 1 }; + + vkCmdCopyImage( copyCmd, this->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, temporary, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy ); + } + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + + imageMemoryBarrier.image = temporary; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + + imageMemoryBarrier.image = this->image; + imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + imageMemoryBarrier.newLayout = descriptor.imageLayout; + vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier ); + device->flushCommandBuffer(copyCmd, true); + + const uint8_t* data; + vmaMapMemory( allocator, allocation, (void**)&data ); + image.loadFromBuffer( data, {this->width, this->height}, 8, 4, false ); + vmaUnmapMemory( allocator, allocation ); + vmaDestroyImage(allocator, temporary, allocation); + return image; +} + ext::vulkan::Texture2D::Texture2D() { type = ext::vulkan::enums::Image::TYPE_2D; viewType = ext::vulkan::enums::Image::VIEW_TYPE_2D; diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index a9f52454..6d8346a6 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -2,38 +2,37 @@ #if UF_USE_XATLAS #include -pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { - struct Pair { +size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) { + struct Entry { size_t index = 0; - size_t command = 0; + size_t commandID = 0; ::xatlas::MeshDecl decl; }; + struct Atlas { + ::xatlas::Atlas* pointer = NULL; + uf::stl::vector entries; + size_t vertexOffset = 0; + }; - uf::stl::vector entries; - entries.reserve(graph.meshes.size()); - uf::stl::vector sources; sources.reserve(graph.meshes.size()); - ::xatlas::Atlas* atlas = ::xatlas::Create(); + uf::stl::unordered_map atlases; + atlases.reserve(graph.meshes.size()); + uf::stl::vector sizes( graph.meshes.size(), 0 ); + + // copy source meshes + // create mesh decls for passing to xatlas for ( auto index = 0; index < graph.meshes.size(); ++index ) { auto& name = graph.meshes[index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - /* - if ( mesh.isInterleaved() ) { - sources.emplace_back(mesh.convert()).updateDescriptor(); - } else { - sources.emplace_back(mesh).updateDescriptor(); - } - */ if ( mesh.isInterleaved() ) { UF_EXCEPTION("unwrapping interleaved mesh is not supported"); } sources.emplace_back(mesh).updateDescriptor(); - uf::Mesh::Input vertexInput = mesh.vertex; uf::Mesh::Attribute positionAttribute; @@ -59,13 +58,19 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { } if ( mesh.indirect.count ) { + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + for ( auto i = 0; i < mesh.indirect.count; ++i ) { + size_t atlasID = combined ? 0 : drawCommands[i].auxID; + vertexInput = mesh.remapVertexInput( i ); indexInput = mesh.remapIndexInput( i ); - auto& entry = entries.emplace_back(); + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); entry.index = index; - entry.command = i; + entry.commandID = i; auto& decl = entry.decl; @@ -82,7 +87,9 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { decl.indexFormat = indexType; } } else { - auto& entry = entries.emplace_back(); + size_t atlasID = 0; + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); entry.index = index; auto& decl = entry.decl; @@ -101,11 +108,18 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { } else UF_EXCEPTION("to-do: not require indices for meshes"); } - for ( auto& mesh : entries ) { - ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas, mesh.decl, entries.size()); - if (error != ::xatlas::AddMeshError::Success) { - ::xatlas::Destroy(atlas); - UF_EXCEPTION(::xatlas::StringForEnum(error)); + // add mesh decls to mesh atlases + // done after the fact since we'll know the total amount of meshes added + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create(); + + for ( auto& entry : atlas.entries ) { + ::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size()); + if (error != ::xatlas::AddMeshError::Success) { + ::xatlas::Destroy(atlas.pointer); + UF_EXCEPTION(::xatlas::StringForEnum(error)); + } } } @@ -119,150 +133,173 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { packOptions.blockAlign = true; packOptions.bilinear = true; - ::xatlas::Generate(atlas, chartOptions, packOptions); + // pack + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + ::xatlas::Generate(atlas.pointer, chartOptions, packOptions); - uf::stl::vector sizes( graph.meshes.size(), 0 ); - for ( auto i = 0; i < atlas->meshCount; ++i ) { - auto& xmesh = atlas->meshes[i]; - auto& entry = entries[i]; - sizes[entry.index] += xmesh.vertexCount; + // get vertices size ahead of time + for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) { + auto& xmesh = atlas.pointer->meshes[i]; + auto& entry = atlas.entries[i]; + // atlas.vertices += xmesh.vertexCount; + sizes[entry.index] += xmesh.vertexCount; + } } + + // resize vertices for ( auto i = 0; i < graph.meshes.size(); ++i ) { auto& name = graph.meshes[i]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; mesh.resizeVertices( sizes[i] ); mesh.updateDescriptor(); + } - if ( mesh.indirect.count ) { - auto& primitive = /*graph.storage*/uf::graph::storage.primitives[name]; - pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + // update vertices + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) { + auto& xmesh = atlas.pointer->meshes[i]; + auto& entry = atlas.entries[i]; + auto& name = graph.meshes[entry.index]; + auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; + auto& source = sources[entry.index]; - size_t vertexOffset = 0; - for ( auto j = 0; j < atlas->meshCount; ++j ) { - auto& entry = entries[j]; - if ( entry.index != i ) continue; + // draw commands + if ( mesh.indirect.count ) { + // vertices + auto srcInput = source.remapVertexInput( entry.commandID ); + auto dstInput = mesh.remapVertexInput( entry.commandID ); + auto vertexCount = xmesh.vertexCount; - auto vertexCount = atlas->meshes[j].vertexCount; + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); - drawCommands[entry.command].vertices = vertexCount; - drawCommands[entry.command].vertexID = vertexOffset; - - primitive[entry.command].drawCommand.vertices = vertexCount; - primitive[entry.command].drawCommand.vertexID = vertexOffset; + drawCommands[entry.commandID].vertices = vertexCount; + primitives[entry.commandID].drawCommand.vertices = vertexCount; - vertexOffset += vertexCount; + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { + // auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.commandID ); + // auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.commandID ); + + auto srcAttribute = source.vertex.attributes[k]; + auto dstAttribute = mesh.vertex.attributes[k]; + + if ( dstAttribute.descriptor.name == "st" ) { + pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) ); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; + } else { + memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride ); + } + } + } + // indices + if ( mesh.index.count ) { + uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.commandID ); + uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); + // uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.commandID ); + uint8_t* pointer = (uint8_t*) static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; + for ( auto index = 0; index < xmesh.indexCount; ++index ) { + switch ( mesh.index.size ) { + case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break; + case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break; + case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break; + } + } + } + } else { + uf::Mesh::Attribute stAttribute; + for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute; + UF_ASSERT( stAttribute.descriptor.name == "st" ); + + // vertices + for ( auto j = 0; j < xmesh.vertexCount; ++j ) { + auto& vertex = xmesh.vertexArray[j]; + auto ref = vertex.xref; + + for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { + auto srcAttribute = source.vertex.attributes[k]; + auto dstAttribute = mesh.vertex.attributes[k]; + + if ( dstAttribute.descriptor.name == "st" ) { + pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j); + st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; + } else { + memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * j, static_cast(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride ); + } + } + /* + if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) { + uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; + uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; + + memcpy( dstAttribute, srcAttribute, mesh.vertex.size ); + + pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset); + st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; + } else for ( auto& attribute : mesh.vertex.attributes ) { + uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size; + uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size; + + if ( attribute.descriptor.name == "st" ) { + pod::Vector2f& st = *(pod::Vector2f*) dstAttribute; + st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height }; + } else { + memcpy( dstAttribute, srcAttribute, attribute.descriptor.size ); + } + } + */ + } + // indices + if ( mesh.index.count ) { + uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data(); + for ( auto index = 0; index < xmesh.indexCount; ++index ) { + switch ( mesh.index.size ) { + case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break; + case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break; + case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break; + } + } + } } + + mesh.updateDescriptor(); } } - for ( auto i = 0; i < atlas->meshCount; i++ ) { - auto& xmesh = atlas->meshes[i]; - auto& entry = entries[i]; - auto& name = graph.meshes[entry.index]; + // update vertexID offsets for indirect commands + for ( auto index = 0; index < graph.meshes.size(); ++index ) { + auto& name = graph.meshes[index]; auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name]; - auto& source = sources[entry.index]; + + if ( !mesh.indirect.count ) continue; - // draw commands - if ( mesh.indirect.count ) { - // vertices - for ( auto j = 0; j < xmesh.vertexCount; ++j ) { - auto& vertex = xmesh.vertexArray[j]; - auto ref = vertex.xref; - for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { - // auto srcAttribute = source.remapVertexAttribute( source.vertex.attributes[k], entry.command ); - // auto dstAttribute = mesh.remapVertexAttribute( mesh.vertex.attributes[k], entry.command ); + auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); - auto srcInput = source.remapVertexInput( entry.command ); - auto dstInput = mesh.remapVertexInput( entry.command ); + size_t vertexID = 0; + for ( auto i = 0; i < mesh.indirect.count; ++i ) { + auto& primitive = primitives[i]; + auto& drawCommand = drawCommands[i]; - auto srcAttribute = source.vertex.attributes[k]; - auto dstAttribute = mesh.vertex.attributes[k]; + drawCommand.vertexID = vertexID; + primitive.drawCommand.vertexID = vertexID; - if ( dstAttribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) ( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) ); - st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height }; - } else { - memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride ); - } - } - } - // indices - if ( mesh.index.count ) { - uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.command ); - uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); - // uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.command ); - uint8_t* pointer = (uint8_t*) static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; - for ( auto index = 0; index < xmesh.indexCount; ++index ) { - switch ( mesh.index.size ) { - case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break; - case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break; - case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break; - } - } - } - } else { - uf::Mesh::Attribute stAttribute; - for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute; - UF_ASSERT( stAttribute.descriptor.name == "st" ); - - // vertices - for ( auto j = 0; j < xmesh.vertexCount; ++j ) { - auto& vertex = xmesh.vertexArray[j]; - auto ref = vertex.xref; - - for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) { - auto srcAttribute = source.vertex.attributes[k]; - auto dstAttribute = mesh.vertex.attributes[k]; - - if ( dstAttribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j); - st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height }; - } else { - memcpy( static_cast(dstAttribute.pointer) + dstAttribute.stride * j, static_cast(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride ); - } - } - /* - if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) { - uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; - uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size; - - memcpy( dstAttribute, srcAttribute, mesh.vertex.size ); - - pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset); - st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height }; - } else for ( auto& attribute : mesh.vertex.attributes ) { - uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size; - uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size; - - if ( attribute.descriptor.name == "st" ) { - pod::Vector2f& st = *(pod::Vector2f*) dstAttribute; - st = { vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height }; - } else { - memcpy( dstAttribute, srcAttribute, attribute.descriptor.size ); - } - } - */ - } - // indices - if ( mesh.index.count ) { - uint8_t* pointer = (uint8_t*) mesh.buffers[mesh.isInterleaved(mesh.index.interleaved) ? mesh.index.interleaved : mesh.index.attributes.front().buffer].data(); - for ( auto index = 0; index < xmesh.indexCount; ++index ) { - switch ( mesh.index.size ) { - case 1: (( uint8_t*) pointer)[index] = xmesh.indexArray[index]; break; - case 2: ((uint16_t*) pointer)[index] = xmesh.indexArray[index]; break; - case 4: ((uint32_t*) pointer)[index] = xmesh.indexArray[index]; break; - } - } - } + vertexID += drawCommand.vertices; } - - mesh.updateDescriptor(); } - pod::Vector2ui size = pod::Vector2ui{ atlas->width, atlas->height }; - ::xatlas::Destroy(atlas); - - return size; + // cleanup + size_t atlasCount = 0; + for ( auto& pair : atlases ) { + auto& atlas = pair.second; + ::xatlas::Destroy(atlas.pointer); + ++atlasCount; + } + return atlasCount; } #endif \ No newline at end of file diff --git a/engine/src/spec/window/dreamcast.cpp b/engine/src/spec/window/dreamcast.cpp index b060a886..fde17503 100644 --- a/engine/src/spec/window/dreamcast.cpp +++ b/engine/src/spec/window/dreamcast.cpp @@ -5,6 +5,9 @@ #include #include +#define UF_OPENGL_CONTEXT_IN_WINDOW 0 +#include + #if UF_ENV_DREAMCAST /* @@ -269,14 +272,71 @@ namespace { } } -UF_API_CALL spec::dreamcast::Window::Window() {} +#include +uf::stl::string spec::dreamcast::malloc_stats( bool verbose ) { + std::stringstream str; + + if ( verbose ) { + str << "malloc Info:\n" + "\tarena " << uf::string::si( mallinfo().arena, "B" ) << " (non-mmapped space allocated from system)\n" + "\tordblks " << uf::string::si( mallinfo().ordblks, "B" ) << " (number of free chunks)\n" + "\tsmblks " << uf::string::si( mallinfo().smblks, "B" ) << " (number of fastbin blocks)\n" + "\tusmblks " << uf::string::si( mallinfo().usmblks, "B" ) << " (maximum total allocated space)\n" + "\tfsmblks " << uf::string::si( mallinfo().fsmblks, "B" ) << " (space available in freed fastbin blocks)\n" + "\tuordblks " << uf::string::si( mallinfo().uordblks, "B" ) << " (total allocated space)\n" + "\tfordblks " << uf::string::si( mallinfo().fordblks, "B" ) << " (total free space)\n" + "\tkeepcost " << uf::string::si( mallinfo().keepcost, "B" ) << " (top-most, releasable (via malloc_trim) space)\n"; + } else { + str << "malloc Info: Free: " << uf::string::si( mallinfo().arena - mallinfo().uordblks, "B" ) << " | Used: " << uf::string::si( mallinfo().uordblks, "B" ); + } + + return str.str(); +} + +uf::stl::string spec::dreamcast::pvr_malloc_stats( bool verbose ) { + std::stringstream str; + + if ( verbose ) { + /* + "PVR malloc Info:\n" + "PVR malloc Info:\n" + "\tarena " << uf::string::si( pvr_int_mallinfo().arena, "B" ) << " (non-mmapped space allocated from system)\n" + "\tordblks " << uf::string::si( pvr_int_mallinfo().ordblks, "B" ) << " (number of free chunks)\n" + "\tsmblks " << uf::string::si( pvr_int_mallinfo().smblks, "B" ) << " (number of fastbin blocks)\n" + "\tusmblks " << uf::string::si( pvr_int_mallinfo().usmblks, "B" ) << " (maximum total allocated space)\n" + "\tfsmblks " << uf::string::si( pvr_int_mallinfo().fsmblks, "B" ) << " (space available in freed fastbin blocks)\n" + "\tuordblks " << uf::string::si( pvr_int_mallinfo().uordblks, "B" ) << " (total allocated space)\n" + "\tfordblks " << uf::string::si( pvr_int_mallinfo().fordblks, "B" ) << " (total free space)\n" + "\tkeepcost " << uf::string::si( pvr_int_mallinfo().keepcost, "B" ) << " (top-most, releasable (via malloc_trim) space)"; + */ + } else { + str << "PVR malloc Info: Free: " << uf::string::si( pvr_mem_available(), "B" ); + } + + + return str.str(); +} + +UF_API_CALL spec::dreamcast::Window::Window() : m_context(NULL) {} void UF_API_CALL spec::dreamcast::Window::create( const spec::dreamcast::Window::vector_t& _size, const spec::dreamcast::Window::title_t& title ) { ::keyboard.device = maple_enum_type(1, MAPLE_FUNC_KEYBOARD); this->setSize(_size); + +#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW + this->m_context = (void*) spec::uni::Context::create( settings, *this ); +#endif } spec::dreamcast::Window::~Window() { +#if UF_OPENGL_CONTEXT_IN_WINDOW + if ( this->m_context ) { + spec::Context* context = (spec::Context*) this->m_context; + context->terminate(); + delete context; + this->m_context = NULL; + } +#endif } void UF_API_CALL spec::dreamcast::Window::terminate() { } @@ -339,12 +399,15 @@ void UF_API_CALL spec::dreamcast::Window::setKeyRepeatEnabled( bool state ) { void UF_API_CALL spec::dreamcast::Window::requestFocus() { } bool UF_API_CALL spec::dreamcast::Window::hasFocus() const { - return true; +// return (uf::Window::focused = true); + return uf::Window::focused; } #include void UF_API_CALL spec::dreamcast::Window::bufferInputs() { + uf::Window::focused = true; + uf::inputs::kbm::states::LShift = GetModifier(KBD_MOD_LSHIFT); uf::inputs::kbm::states::RShift = GetModifier(KBD_MOD_RSHIFT); @@ -357,109 +420,109 @@ void UF_API_CALL spec::dreamcast::Window::bufferInputs() { uf::inputs::kbm::states::LSystem = GetModifier(KBD_MOD_S1); uf::inputs::kbm::states::RSystem = GetModifier(KBD_MOD_S2); -// uf::inputs::kbm::states::Menu = KBD_KEY_APPS; - uf::inputs::kbm::states::SemiColon = KBD_KEY_SEMICOLON; - uf::inputs::kbm::states::Slash = KBD_KEY_SLASH; -// uf::inputs::kbm::states::Equal = KBD_KEY_EQUAL; - uf::inputs::kbm::states::Dash = KBD_KEY_MINUS; - uf::inputs::kbm::states::LBracket = KBD_KEY_LBRACKET; - uf::inputs::kbm::states::RBracket = KBD_KEY_RBRACKET; - uf::inputs::kbm::states::Comma = KBD_KEY_COMMA; - uf::inputs::kbm::states::Period = KBD_KEY_PERIOD; - uf::inputs::kbm::states::Quote = KBD_KEY_QUOTE; - uf::inputs::kbm::states::BackSlash = KBD_KEY_BACKSLASH; - uf::inputs::kbm::states::Tilde = KBD_KEY_TILDE; +// uf::inputs::kbm::states::Menu = GetKeyState(KBD_KEY_APPS); + uf::inputs::kbm::states::SemiColon = GetKeyState(KBD_KEY_SEMICOLON); + uf::inputs::kbm::states::Slash = GetKeyState(KBD_KEY_SLASH); +// uf::inputs::kbm::states::Equal = GetKeyState(KBD_KEY_EQUAL); + uf::inputs::kbm::states::Dash = GetKeyState(KBD_KEY_MINUS); + uf::inputs::kbm::states::LBracket = GetKeyState(KBD_KEY_LBRACKET); + uf::inputs::kbm::states::RBracket = GetKeyState(KBD_KEY_RBRACKET); + uf::inputs::kbm::states::Comma = GetKeyState(KBD_KEY_COMMA); + uf::inputs::kbm::states::Period = GetKeyState(KBD_KEY_PERIOD); + uf::inputs::kbm::states::Quote = GetKeyState(KBD_KEY_QUOTE); + uf::inputs::kbm::states::BackSlash = GetKeyState(KBD_KEY_BACKSLASH); + uf::inputs::kbm::states::Tilde = GetKeyState(KBD_KEY_TILDE); - uf::inputs::kbm::states::Escape = KBD_KEY_ESCAPE; - uf::inputs::kbm::states::Space = KBD_KEY_SPACE; - uf::inputs::kbm::states::Enter = KBD_KEY_ENTER; - uf::inputs::kbm::states::BackSpace = KBD_KEY_BACKSPACE; - uf::inputs::kbm::states::Tab = KBD_KEY_TAB; - uf::inputs::kbm::states::PageUp = KBD_KEY_PGUP; - uf::inputs::kbm::states::PageDown = KBD_KEY_PGDOWN; - uf::inputs::kbm::states::End = KBD_KEY_END; - uf::inputs::kbm::states::Home = KBD_KEY_HOME; - uf::inputs::kbm::states::Insert = KBD_KEY_INSERT; - uf::inputs::kbm::states::Delete = KBD_KEY_DEL; - uf::inputs::kbm::states::Add = KBD_KEY_PAD_PLUS; - uf::inputs::kbm::states::Subtract = KBD_KEY_PAD_MINUS; - uf::inputs::kbm::states::Multiply = KBD_KEY_PAD_MULTIPLY; - uf::inputs::kbm::states::Divide = KBD_KEY_PAD_DIVIDE; - uf::inputs::kbm::states::Pause = KBD_KEY_PAUSE; + uf::inputs::kbm::states::Escape = GetKeyState(KBD_KEY_ESCAPE); + uf::inputs::kbm::states::Space = GetKeyState(KBD_KEY_SPACE); + uf::inputs::kbm::states::Enter = GetKeyState(KBD_KEY_ENTER); + uf::inputs::kbm::states::BackSpace = GetKeyState(KBD_KEY_BACKSPACE); + uf::inputs::kbm::states::Tab = GetKeyState(KBD_KEY_TAB); + uf::inputs::kbm::states::PageUp = GetKeyState(KBD_KEY_PGUP); + uf::inputs::kbm::states::PageDown = GetKeyState(KBD_KEY_PGDOWN); + uf::inputs::kbm::states::End = GetKeyState(KBD_KEY_END); + uf::inputs::kbm::states::Home = GetKeyState(KBD_KEY_HOME); + uf::inputs::kbm::states::Insert = GetKeyState(KBD_KEY_INSERT); + uf::inputs::kbm::states::Delete = GetKeyState(KBD_KEY_DEL); + uf::inputs::kbm::states::Add = GetKeyState(KBD_KEY_PAD_PLUS); + uf::inputs::kbm::states::Subtract = GetKeyState(KBD_KEY_PAD_MINUS); + uf::inputs::kbm::states::Multiply = GetKeyState(KBD_KEY_PAD_MULTIPLY); + uf::inputs::kbm::states::Divide = GetKeyState(KBD_KEY_PAD_DIVIDE); + uf::inputs::kbm::states::Pause = GetKeyState(KBD_KEY_PAUSE); - uf::inputs::kbm::states::F1 = KBD_KEY_F1; - uf::inputs::kbm::states::F2 = KBD_KEY_F2; - uf::inputs::kbm::states::F3 = KBD_KEY_F3; - uf::inputs::kbm::states::F4 = KBD_KEY_F4; - uf::inputs::kbm::states::F5 = KBD_KEY_F5; - uf::inputs::kbm::states::F6 = KBD_KEY_F6; - uf::inputs::kbm::states::F7 = KBD_KEY_F7; - uf::inputs::kbm::states::F8 = KBD_KEY_F8; - uf::inputs::kbm::states::F9 = KBD_KEY_F9; - uf::inputs::kbm::states::F10 = KBD_KEY_F10; - uf::inputs::kbm::states::F11 = KBD_KEY_F11; - uf::inputs::kbm::states::F12 = KBD_KEY_F12; -// uf::inputs::kbm::states::F13 = KBD_KEY_F13; -// uf::inputs::kbm::states::F14 = KBD_KEY_F14; -// uf::inputs::kbm::states::F15 = KBD_KEY_F15; + uf::inputs::kbm::states::F1 = GetKeyState(KBD_KEY_F1); + uf::inputs::kbm::states::F2 = GetKeyState(KBD_KEY_F2); + uf::inputs::kbm::states::F3 = GetKeyState(KBD_KEY_F3); + uf::inputs::kbm::states::F4 = GetKeyState(KBD_KEY_F4); + uf::inputs::kbm::states::F5 = GetKeyState(KBD_KEY_F5); + uf::inputs::kbm::states::F6 = GetKeyState(KBD_KEY_F6); + uf::inputs::kbm::states::F7 = GetKeyState(KBD_KEY_F7); + uf::inputs::kbm::states::F8 = GetKeyState(KBD_KEY_F8); + uf::inputs::kbm::states::F9 = GetKeyState(KBD_KEY_F9); + uf::inputs::kbm::states::F10 = GetKeyState(KBD_KEY_F10); + uf::inputs::kbm::states::F11 = GetKeyState(KBD_KEY_F11); + uf::inputs::kbm::states::F12 = GetKeyState(KBD_KEY_F12); +// uf::inputs::kbm::states::F13 = GetKeyState(KBD_KEY_F13); +// uf::inputs::kbm::states::F14 = GetKeyState(KBD_KEY_F14); +// uf::inputs::kbm::states::F15 = GetKeyState(KBD_KEY_F15); - uf::inputs::kbm::states::Left = KBD_KEY_LEFT; - uf::inputs::kbm::states::Right = KBD_KEY_RIGHT; - uf::inputs::kbm::states::Up = KBD_KEY_UP; - uf::inputs::kbm::states::Down = KBD_KEY_DOWN; + uf::inputs::kbm::states::Left = GetKeyState(KBD_KEY_LEFT); + uf::inputs::kbm::states::Right = GetKeyState(KBD_KEY_RIGHT); + uf::inputs::kbm::states::Up = GetKeyState(KBD_KEY_UP); + uf::inputs::kbm::states::Down = GetKeyState(KBD_KEY_DOWN); - uf::inputs::kbm::states::Numpad0 = KBD_KEY_PAD_0; - uf::inputs::kbm::states::Numpad1 = KBD_KEY_PAD_1; - uf::inputs::kbm::states::Numpad2 = KBD_KEY_PAD_2; - uf::inputs::kbm::states::Numpad3 = KBD_KEY_PAD_3; - uf::inputs::kbm::states::Numpad4 = KBD_KEY_PAD_4; - uf::inputs::kbm::states::Numpad5 = KBD_KEY_PAD_5; - uf::inputs::kbm::states::Numpad6 = KBD_KEY_PAD_6; - uf::inputs::kbm::states::Numpad7 = KBD_KEY_PAD_7; - uf::inputs::kbm::states::Numpad8 = KBD_KEY_PAD_8; - uf::inputs::kbm::states::Numpad9 = KBD_KEY_PAD_9; + uf::inputs::kbm::states::Numpad0 = GetKeyState(KBD_KEY_PAD_0); + uf::inputs::kbm::states::Numpad1 = GetKeyState(KBD_KEY_PAD_1); + uf::inputs::kbm::states::Numpad2 = GetKeyState(KBD_KEY_PAD_2); + uf::inputs::kbm::states::Numpad3 = GetKeyState(KBD_KEY_PAD_3); + uf::inputs::kbm::states::Numpad4 = GetKeyState(KBD_KEY_PAD_4); + uf::inputs::kbm::states::Numpad5 = GetKeyState(KBD_KEY_PAD_5); + uf::inputs::kbm::states::Numpad6 = GetKeyState(KBD_KEY_PAD_6); + uf::inputs::kbm::states::Numpad7 = GetKeyState(KBD_KEY_PAD_7); + uf::inputs::kbm::states::Numpad8 = GetKeyState(KBD_KEY_PAD_8); + uf::inputs::kbm::states::Numpad9 = GetKeyState(KBD_KEY_PAD_9); - uf::inputs::kbm::states::Q = KBD_KEY_Q; - uf::inputs::kbm::states::W = KBD_KEY_W; - uf::inputs::kbm::states::E = KBD_KEY_E; - uf::inputs::kbm::states::R = KBD_KEY_R; - uf::inputs::kbm::states::T = KBD_KEY_T; - uf::inputs::kbm::states::Y = KBD_KEY_Y; - uf::inputs::kbm::states::U = KBD_KEY_U; - uf::inputs::kbm::states::I = KBD_KEY_I; - uf::inputs::kbm::states::O = KBD_KEY_O; - uf::inputs::kbm::states::P = KBD_KEY_P; + uf::inputs::kbm::states::Q = GetKeyState(KBD_KEY_Q); + uf::inputs::kbm::states::W = GetKeyState(KBD_KEY_W); + uf::inputs::kbm::states::E = GetKeyState(KBD_KEY_E); + uf::inputs::kbm::states::R = GetKeyState(KBD_KEY_R); + uf::inputs::kbm::states::T = GetKeyState(KBD_KEY_T); + uf::inputs::kbm::states::Y = GetKeyState(KBD_KEY_Y); + uf::inputs::kbm::states::U = GetKeyState(KBD_KEY_U); + uf::inputs::kbm::states::I = GetKeyState(KBD_KEY_I); + uf::inputs::kbm::states::O = GetKeyState(KBD_KEY_O); + uf::inputs::kbm::states::P = GetKeyState(KBD_KEY_P); - uf::inputs::kbm::states::A = KBD_KEY_A; - uf::inputs::kbm::states::S = KBD_KEY_S; - uf::inputs::kbm::states::D = KBD_KEY_D; - uf::inputs::kbm::states::F = KBD_KEY_F; - uf::inputs::kbm::states::G = KBD_KEY_G; - uf::inputs::kbm::states::H = KBD_KEY_H; - uf::inputs::kbm::states::J = KBD_KEY_J; - uf::inputs::kbm::states::K = KBD_KEY_K; - uf::inputs::kbm::states::L = KBD_KEY_L; + uf::inputs::kbm::states::A = GetKeyState(KBD_KEY_A); + uf::inputs::kbm::states::S = GetKeyState(KBD_KEY_S); + uf::inputs::kbm::states::D = GetKeyState(KBD_KEY_D); + uf::inputs::kbm::states::F = GetKeyState(KBD_KEY_F); + uf::inputs::kbm::states::G = GetKeyState(KBD_KEY_G); + uf::inputs::kbm::states::H = GetKeyState(KBD_KEY_H); + uf::inputs::kbm::states::J = GetKeyState(KBD_KEY_J); + uf::inputs::kbm::states::K = GetKeyState(KBD_KEY_K); + uf::inputs::kbm::states::L = GetKeyState(KBD_KEY_L); - uf::inputs::kbm::states::Z = KBD_KEY_Z; - uf::inputs::kbm::states::X = KBD_KEY_X; - uf::inputs::kbm::states::C = KBD_KEY_C; - uf::inputs::kbm::states::V = KBD_KEY_V; - uf::inputs::kbm::states::B = KBD_KEY_B; - uf::inputs::kbm::states::N = KBD_KEY_N; - uf::inputs::kbm::states::M = KBD_KEY_M; + uf::inputs::kbm::states::Z = GetKeyState(KBD_KEY_Z); + uf::inputs::kbm::states::X = GetKeyState(KBD_KEY_X); + uf::inputs::kbm::states::C = GetKeyState(KBD_KEY_C); + uf::inputs::kbm::states::V = GetKeyState(KBD_KEY_V); + uf::inputs::kbm::states::B = GetKeyState(KBD_KEY_B); + uf::inputs::kbm::states::N = GetKeyState(KBD_KEY_N); + uf::inputs::kbm::states::M = GetKeyState(KBD_KEY_M); - uf::inputs::kbm::states::Num1 = KBD_KEY_1; - uf::inputs::kbm::states::Num2 = KBD_KEY_2; - uf::inputs::kbm::states::Num3 = KBD_KEY_3; - uf::inputs::kbm::states::Num4 = KBD_KEY_4; - uf::inputs::kbm::states::Num5 = KBD_KEY_5; - uf::inputs::kbm::states::Num6 = KBD_KEY_6; - uf::inputs::kbm::states::Num7 = KBD_KEY_7; - uf::inputs::kbm::states::Num8 = KBD_KEY_8; - uf::inputs::kbm::states::Num9 = KBD_KEY_9; - uf::inputs::kbm::states::Num0 = KBD_KEY_0; + uf::inputs::kbm::states::Num1 = GetKeyState(KBD_KEY_1); + uf::inputs::kbm::states::Num2 = GetKeyState(KBD_KEY_2); + uf::inputs::kbm::states::Num3 = GetKeyState(KBD_KEY_3); + uf::inputs::kbm::states::Num4 = GetKeyState(KBD_KEY_4); + uf::inputs::kbm::states::Num5 = GetKeyState(KBD_KEY_5); + uf::inputs::kbm::states::Num6 = GetKeyState(KBD_KEY_6); + uf::inputs::kbm::states::Num7 = GetKeyState(KBD_KEY_7); + uf::inputs::kbm::states::Num8 = GetKeyState(KBD_KEY_8); + uf::inputs::kbm::states::Num9 = GetKeyState(KBD_KEY_9); + uf::inputs::kbm::states::Num0 = GetKeyState(KBD_KEY_0); } -void UF_API_CALL spec::dreamcast::Window::processEvents() { +void UF_API_CALL spec::dreamcast::Window::processEvents() { if ( !::keyboard.device ) ::keyboard.device = maple_enum_type(0, MAPLE_FUNC_KEYBOARD); if ( ::keyboard.device ) ::keyboard.state = (kbd_state_t*) maple_dev_status(::keyboard.device); @@ -569,7 +632,18 @@ void UF_API_CALL spec::dreamcast::Window::toggleFullscreen( bool borderless ) { bool UF_API_CALL spec::dreamcast::Window::isKeyPressed(const uf::stl::string& key) { auto code = GetKeyCode(key); auto keys = GetKeys(); + UF_MSG_DEBUG( key << " " << code << " " << keys.size() ); for ( auto key : keys ) if ( key == code ) return true; - return false; + return false;// } + +void UF_API_CALL spec::dreamcast::Window::display() { +#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW + if ( this->m_context ){ + spec::Context* context = (spec::Context*) this->m_context; + if ( context->setActive(true) ) context->display(); + } +#endif +} + #endif \ No newline at end of file diff --git a/engine/src/spec/window/universal.cpp b/engine/src/spec/window/universal.cpp index 7bd7c5b1..4523d643 100644 --- a/engine/src/spec/window/universal.cpp +++ b/engine/src/spec/window/universal.cpp @@ -4,6 +4,8 @@ #include #include + +bool spec::uni::Window::focused = false; /* void UF_API_CALL spec::uni::Window::pushEvent( const uf::ReadableHook::name_t& name, const uf::ReadableHook::argument_t& argument ) { if ( !uf::hooks.prefersReadable() ) return; @@ -76,6 +78,7 @@ void UF_API_CALL spec::uni::Window::pushEvent( const pod::Hook::userdata_t& payl this->m_events.push({ header.type, std::move(payload) }); } */ +#if 0 void UF_API_CALL spec::uni::Window::processEvents() { } bool UF_API_CALL spec::uni::Window::isKeyPressed(const uf::stl::string& key) { @@ -151,4 +154,5 @@ bool UF_API_CALL spec::uni::Window::pollEvents( bool block ) { } return true; #endif -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/engine/src/spec/window/windows.cpp b/engine/src/spec/window/windows.cpp index 608e2a9f..c3568c92 100644 --- a/engine/src/spec/window/windows.cpp +++ b/engine/src/spec/window/windows.cpp @@ -6,6 +6,9 @@ #include #include +#define UF_OPENGL_CONTEXT_IN_WINDOW 0 +#include + #define UF_HOOK_USE_USERDATA 1 #define UF_HOOK_USE_JSON 0 @@ -421,6 +424,7 @@ namespace { UF_API_CALL spec::win32::Window::Window() : m_handle (NULL), + m_context (NULL), m_callback (0), m_cursor (NULL), m_icon (NULL), @@ -453,6 +457,7 @@ UF_API_CALL spec::win32::Window::Window( spec::win32::Window::handle_t handle ) } UF_API_CALL spec::win32::Window::Window( const spec::win32::Window::vector_t& size, const spec::win32::Window::title_t& title ) : m_handle (NULL), + m_context (NULL), m_callback (0), m_cursor (NULL), m_icon (NULL), @@ -506,6 +511,10 @@ void UF_API_CALL spec::win32::Window::create( const spec::win32::Window::vector_ // m_callback = SetWindowLongPtrW(this->m_handle, GWLP_WNDPROC, reinterpret_cast(&::globalOnEvent)); ++windowCount; + +#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW + this->m_context = (void*) spec::uni::Context::create( settings, *this ); +#endif } spec::win32::Window::~Window() { @@ -516,6 +525,15 @@ spec::win32::Window::~Window() { } else { SetWindowLongPtrW( this->m_handle, GWLP_WNDPROC, this->m_callback ); } + +#if UF_OPENGL_CONTEXT_IN_WINDOW + if ( this->m_context ) { + spec::Context* context = (spec::Context*) this->m_context; + context->terminate(); + delete context; + this->m_context = NULL; + } +#endif } void UF_API_CALL spec::win32::Window::terminate() { if ( this == (spec::win32::Window*) fullscreenWindow ) { @@ -663,6 +681,8 @@ bool UF_API_CALL spec::win32::Window::hasFocus() const { } void UF_API_CALL spec::win32::Window::bufferInputs() { + uf::Window::focused = this->hasFocus(); + uf::inputs::kbm::states::LShift = GetAsyncKeyState(VK_LSHIFT) & 0x8000; uf::inputs::kbm::states::RShift = GetAsyncKeyState(VK_RSHIFT) & 0x8000; @@ -1450,7 +1470,7 @@ void UF_API_CALL spec::win32::Window::toggleFullscreen( bool borderless ) { } bool UF_API_CALL spec::win32::Window::isKeyPressed(const uf::stl::string& key) { - return GetAsyncKeyState( GetKeyCode( key ) ) & 0x8000; + return uf::Window::focused && (GetAsyncKeyState( GetKeyCode( key ) ) & 0x8000); } uf::stl::string UF_API_CALL spec::win32::Window::getKey(WPARAM key, LPARAM flags) { return GetKeyName( key, flags ); @@ -1469,4 +1489,14 @@ void UF_API_CALL spec::win32::Window::createSurface( VkInstance instance, VkSurf vkCreateWin32SurfaceKHR( instance, &surfaceCreateInfo, nullptr, &surface); } #endif + +void UF_API_CALL spec::win32::Window::display() { +#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW + if ( this->m_context ){ + spec::Context* context = (spec::Context*) this->m_context; + if ( context->setActive(true) ) context->display(); + } +#endif +} + #endif \ No newline at end of file diff --git a/engine/src/utils/mesh/mesh.cpp b/engine/src/utils/mesh/mesh.cpp index 5400f6ab..75c93c29 100644 --- a/engine/src/utils/mesh/mesh.cpp +++ b/engine/src/utils/mesh/mesh.cpp @@ -284,11 +284,11 @@ std::string uf::Mesh::printInstances( bool full ) const { } std::string uf::Mesh::printIndirects( bool full ) const { std::stringstream str; - str << "Indirect: " << PRINT_HEADER( indirect ) << "{ indices, instances, indexID, vertexID, instanceID, padding1, padding2, vertices }\n"; + str << "Indirect: " << PRINT_HEADER( indirect ) << "{ indices, instances, indexID, vertexID, instanceID, auxID, materialID, vertices }\n"; if ( full ) for ( auto i = 0; i < indirect.count; ++i ) { auto& buffer = getBuffer( indirect ); auto& drawCommand = *(const pod::DrawCommand*) (&buffer[i * indirect.size]); - str << "[" << i << "]: {" << drawCommand.indices << ", " << drawCommand.instances << ", " << drawCommand.indexID << ", " << drawCommand.vertexID << ", " << drawCommand.instanceID << ", " << drawCommand.padding1 << ", " << drawCommand.padding2 << ", " << drawCommand.vertices << "}\n"; + str << "[" << i << "]: {" << drawCommand.indices << ", " << drawCommand.instances << ", " << drawCommand.indexID << ", " << drawCommand.vertexID << ", " << drawCommand.instanceID << ", " << drawCommand.auxID << ", " << drawCommand.materialID << ", " << drawCommand.vertices << "}\n"; } return str.str(); } diff --git a/engine/src/utils/window/window.cpp b/engine/src/utils/window/window.cpp deleted file mode 100644 index a07e1ee4..00000000 --- a/engine/src/utils/window/window.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include -#if !UF_USE_SFML -#define UF_OPENGL_CONTEXT_IN_WINDOW 0 -#include -#include -bool uf::Window::focused = false; - -// C-tors -UF_API_CALL uf::Window::Window() : - m_window(NULL), - m_context(NULL) -{ - -} -UF_API_CALL uf::Window::Window( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title, const spec::Context::Settings& settings ) : Window() { - this->create(size, title, settings); -} -void UF_API_CALL uf::Window::create( const spec::uni::Window::vector_t& size, const spec::uni::Window::title_t& title, const spec::Context::Settings& settings ) { - this->m_window = new uf::Window::window_t; - this->m_window->create( size, title ); -#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW - this->m_context = (spec::Context*) spec::uni::Context::create( settings, *this->m_window ); -#endif -} -// D-tors -uf::Window::~Window() { - this->terminate(); -} -void UF_API_CALL uf::Window::terminate() { -#if UF_OPENGL_CONTEXT_IN_WINDOW - if ( this->m_context ) { - this->m_context->terminate(); - delete this->m_context; - this->m_context = NULL; - } -#endif - if ( this->m_window ) { - this->m_window->terminate(); - delete this->m_window; - this->m_window = NULL; - } -} -// Gets -spec::uni::Window::vector_t UF_API_CALL uf::Window::getPosition() const { - static spec::uni::Window::vector_t null = {}; - return this->m_window ? this->m_window->getPosition() : null; -} -spec::uni::Window::vector_t UF_API_CALL uf::Window::getSize() const { - static spec::uni::Window::vector_t null = {}; - return this->m_window ? this->m_window->getSize() : null; -} -size_t UF_API_CALL uf::Window::getRefreshRate() const { - static spec::uni::Window::vector_t null = {}; - return this->m_window ? this->m_window->getRefreshRate() : 0; -} -// Attribute modifiers -void UF_API_CALL uf::Window::setPosition( const spec::uni::Window::vector_t& position ) { - if ( !this->m_window ) return; - this->m_window->setPosition(position); -} -void UF_API_CALL uf::Window::centerWindow() { - if ( !this->m_window ) return; - this->m_window->centerWindow(); -} -void UF_API_CALL uf::Window::setMousePosition( const spec::uni::Window::vector_t& position ) { - if ( !this->m_window ) return; - this->m_window->setMousePosition(position); -} -spec::uni::Window::vector_t UF_API_CALL uf::Window::getMousePosition() { - return this->m_window ? this->m_window->getMousePosition() : spec::uni::Window::vector_t{ 0, 0 }; -} -void UF_API_CALL uf::Window::setSize( const spec::uni::Window::vector_t& size ) { - if ( !this->m_window ) return; - this->m_window->setSize(size); -} -void UF_API_CALL uf::Window::setTitle( const spec::uni::Window::title_t& title ) { - if ( !this->m_window ) return; - this->m_window->setTitle(title); - - ext::json::Value json; - uf::stl::string hook = "window:Title.Changed"; - json["type"] = hook; - json["invoker"] = "os"; - json["window"]["title"] = uf::stl::string(title); - uf::hooks.call( hook, json ); -} -void UF_API_CALL uf::Window::setIcon( const spec::uni::Window::vector_t& size, uint8_t* pixels ) { - if ( !this->m_window ) return; - this->m_window->setIcon(size, pixels); -} -void UF_API_CALL uf::Window::setVisible( bool visibility ) { - if ( !this->m_window ) return; - this->m_window->setVisible(visibility); -} -void UF_API_CALL uf::Window::setCursorVisible( bool visibility ) { - if ( !this->m_window ) return; - this->m_window->setCursorVisible(visibility); -} -void UF_API_CALL uf::Window::setKeyRepeatEnabled( bool state ) { - if ( !this->m_window ) return; - this->m_window->setKeyRepeatEnabled(state); -} -void UF_API_CALL uf::Window::setMouseGrabbed( bool state ) { - if ( !this->m_window ) return; - this->m_window->setMouseGrabbed(state); -} - -void UF_API_CALL uf::Window::requestFocus() { - if ( !this->m_window ) return; - this->m_window->requestFocus(); -} -bool UF_API_CALL uf::Window::hasFocus() const { - return uf::Window::focused = (this->m_window ? this->m_window->hasFocus() : false); -} -pod::Vector2ui UF_API_CALL uf::Window::getResolution() { - return uf::Window::window_t::getResolution(); -} -void UF_API_CALL uf::Window::toggleFullscreen( bool borderless ) { - if ( !this->m_window ) return; - this->m_window->toggleFullscreen( borderless ); -} -// Update -void UF_API_CALL uf::Window::bufferInputs() { - if ( !this->m_window ) return; - this->m_window->bufferInputs(); -} -void UF_API_CALL uf::Window::processEvents() { - if ( !this->m_window ) return; - this->m_window->processEvents(); -} -bool UF_API_CALL uf::Window::pollEvents( bool block ) { - return this->m_window ? this->m_window->pollEvents(block) : false; -} -bool UF_API_CALL uf::Window::isKeyPressed( const uf::stl::string& key ) { - return uf::Window::focused && uf::Window::window_t::isKeyPressed(key); -} -bool UF_API_CALL uf::Window::setActive(bool active) { -#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW - if ( this->m_context ) { - if ( this->m_context->setActive(active) ) return true; - uf::iostream << "[" << uf::IoStream::Color()("Red") << "ERROR" << "]" << "Failed to activate the window's context" << "\n"; - return false; - } -#endif - return false; -} -#if UF_USE_VULKAN -uf::stl::vector UF_API_CALL uf::Window::getExtensions( bool x ) { - return this->m_window->getExtensions( x ); -} -void UF_API_CALL uf::Window::createSurface( VkInstance instance, VkSurfaceKHR& surface ) { - this->m_window->createSurface( instance, surface ); -} -#endif - -/*virtual*/ uf::Window::window_t* UF_API_CALL uf::Window::getHandle() { - return this->m_window; -} -/*virtual*/ const uf::Window::window_t* UF_API_CALL uf::Window::getHandle() const { - return this->m_window; -} - - -//////////////////////////////////////////////////////////// - -#include -#include -#include -void UF_API_CALL uf::Window::display() { -#if UF_USE_OPENGL && UF_OPENGL_CONTEXT_IN_WINDOW - if ( this->m_context && this->setActive() ) this->m_context->display(); -#endif -} - -#endif \ No newline at end of file diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index c1f2415c..80ea207d 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -1,5 +1,5 @@ #include -#if !UF_ENV_DREAMCAST +#if UF_USE_VULKAN #include "behavior.h" #include @@ -57,7 +57,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { renderMode.metadata.type = "single"; renderMode.metadata.pipeline = "baking"; renderMode.metadata.samples = 1; - // renderMode.metadata.layers = metadata.max.layers; + // renderMode.metadata.views = metadata.max.layers; // gl_Layer doesn't work renderMode.metadata.json["descriptor"]["cull mode"] = "none"; renderMode.width = metadata.size.x; @@ -74,6 +74,8 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { for ( auto& texture : uf::graph::storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture); for ( auto& texture : uf::graph::storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture); + metadata.buffers.baked.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.size.x, metadata.size.y, metadata.max.layers, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL ); + scene.process([&]( uf::Entity* entity ) { if ( !entity->hasComponent() ) return; auto& graphic = entity->getComponent(); @@ -81,6 +83,8 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { for ( auto& t : textures2D ) shader.textures.emplace_back().aliasTexture( t ); for ( auto& t : texturesCube ) shader.textures.emplace_back().aliasTexture( t ); + + shader.textures.emplace_back().aliasTexture( metadata.buffers.baked ); }); UF_MSG_DEBUG("Finished initialiation."); }); @@ -116,10 +120,13 @@ SAVE: { #if 1 renderMode.execute = false; UF_MSG_DEBUG("Baking..."); - auto image = renderMode.screenshot(); - uf::stl::string filename = metadata.output; - bool status = image.save(filename); - UF_MSG_DEBUG("Writing to " << filename << ": " << status); + for ( size_t i = 0; i < metadata.max.layers; ++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) ); + bool status = image.save(filename); + UF_MSG_DEBUG("Writing to " << filename << ": " << status); + } UF_MSG_DEBUG("Baked."); metadata.initialized.map = true; diff --git a/ext/behaviors/baking/behavior.h b/ext/behaviors/baking/behavior.h index b4357535..842146da 100644 --- a/ext/behaviors/baking/behavior.h +++ b/ext/behaviors/baking/behavior.h @@ -22,6 +22,8 @@ namespace ext { size_t material = 0; size_t texture = 0; size_t light = 0; + + uf::renderer::Texture3D baked; } buffers; struct { size_t textures2D = 1024; diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 09068186..9450e448 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -314,7 +314,70 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { metadata.shader.parameters[metadata.shader.time] = uf::physics::time::current; } #endif -#if UF_USE_VULKAN +#if UF_USE_OPENGL + if ( metadata.light.enabled ) { + auto& graph = this->getGraph(); + auto& controller = this->getController(); + auto& camera = controller.getComponent(); + auto& controllerMetadata = controller.getComponent(); + auto& controllerTransform = controller.getComponent>(); + auto& metadata = this->getComponent(); + auto& metadataVxgi = this->getComponent(); + auto& metadataJson = this->getComponent(); + + struct LightInfo { + uf::Entity* entity = NULL; + pod::Vector4f position = {0,0,0,1}; // OpenGL requires a W + pod::Vector4f color = {0,0,0,1}; // OpenGL requires an alpha + float distance = 0; + float power = 0; + }; + uf::stl::vector entities; + for ( auto entity : graph ) { + if ( entity == this || entity == &controller || !entity->hasComponent() ) continue; + auto& metadata = entity->getComponent(); + if ( metadata.power <= 0 ) continue; + auto flatten = uf::transform::flatten( entity->getComponent>() ); + LightInfo& info = entities.emplace_back(LightInfo{ + .entity = entity, + .position = flatten.position, + .color = metadata.color, + .distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ), + .power = metadata.power, + }); + info.position.w = 1; + info.color.w = 1; + } + std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){ + return l.distance < r.distance; + }); + + static GLint glMaxLights = 0; + if ( !glMaxLights ) glGetIntegerv(GL_MAX_LIGHTS, &glMaxLights); + metadata.light.max = std::min( (uint32_t) glMaxLights, metadata.light.max ); + + // add lighting + { + uint32_t i = 0; + for ( ; i < entities.size() && i < metadata.light.max; ++i ) { + auto& info = entities[i]; + // uf::Entity* entity = info.entity; + GLenum target = GL_LIGHT0+i; + GL_ERROR_CHECK(glEnable(target)); + GL_ERROR_CHECK(glLightfv(target, GL_AMBIENT, &metadata.light.ambient[0])); + GL_ERROR_CHECK(glLightfv(target, GL_SPECULAR, &metadata.light.specular[0])); + GL_ERROR_CHECK(glLightfv(target, GL_DIFFUSE, &info.color[0])); + GL_ERROR_CHECK(glLightfv(target, GL_POSITION, &info.position[0])); + GL_ERROR_CHECK(glLightf(target, GL_CONSTANT_ATTENUATION, 0.0f)); + GL_ERROR_CHECK(glLightf(target, GL_LINEAR_ATTENUATION, 0)); + GL_ERROR_CHECK(glLightf(target, GL_QUADRATIC_ATTENUATION, 1.0f / info.power)); + + // UF_MSG_DEBUG( i << " | " << uf::vector::toString( metadata.light.ambient ) << " | " << uf::vector::toString( metadata.light.specular ) << " | " << uf::vector::toString( info.color ) << " | " << uf::vector::toString( info.position ) << " | " << info.power ); + } + for ( ; i < metadata.light.max; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i)); + } + } +#elif UF_USE_VULKAN { auto& graph = this->getGraph(); auto& controller = this->getController(); @@ -562,6 +625,11 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali } #if UF_USE_OPENGL_FIXED_FUNCTION uf::renderer::states::rebuild = true; + if ( light.enabled ) { + GL_ERROR_CHECK(glEnable(GL_LIGHTING)); + } else { + GL_ERROR_CHECK(glDisable(GL_LIGHTING)); + } #endif if ( uf::renderer::settings::experimental::bloom ) { @@ -608,58 +676,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string auto& renderMode = uf::renderer::getRenderMode(renderModeName, true); auto blitters = renderMode.getBlitters(); - -#if UF_USE_OPENGL - struct LightInfo { - uf::Entity* entity = NULL; - pod::Vector3f position = {0,0,0}; - float w = 1; // OpenGL requires a W - pod::Vector4f color = {0,0,0,1}; // OpenGL requires an alpha - float distance = 0; - float power = 0; - }; - uf::stl::vector entities; - for ( auto entity : graph ) { - if ( entity == this || entity == &controller || !entity->hasComponent() ) continue; - auto& metadata = entity->getComponent(); - if ( metadata.power <= 0 ) continue; - auto flatten = uf::transform::flatten( entity->getComponent>() ); - LightInfo& info = entities.emplace_back(LightInfo{ - .entity = entity, - .position = flatten.position, - .w = 1, - .color = metadata.color, - .distance = uf::vector::magnitude( uf::vector::subtract( flatten.position, controllerTransform.position ) ), - .power = metadata.power, - }); - } - std::sort( entities.begin(), entities.end(), [&]( LightInfo& l, LightInfo& r ){ - return l.distance < r.distance; - }); - static GLint glMaxLights = 0; - if ( !glMaxLights ) glGetIntegerv(GL_MAX_LIGHTS, &glMaxLights); - metadata.light.max = std::min( (uint32_t) glMaxLights, metadata.light.max ); - - // add lighting - { - uint32_t i = 0; - for ( ; i < entities.size() && i < metadata.light.max; ++i ) { - auto& info = entities[i]; - uf::Entity* entity = info.entity; - GLenum target = GL_LIGHT0+i; - GL_ERROR_CHECK(glEnable(target)); - GL_ERROR_CHECK(glLightfv(target, GL_AMBIENT, &metadata.light.ambient[0])); - GL_ERROR_CHECK(glLightfv(target, GL_SPECULAR, &metadata.light.specular[0])); - GL_ERROR_CHECK(glLightfv(target, GL_DIFFUSE, &info.color[0])); - GL_ERROR_CHECK(glLightfv(target, GL_POSITION, &info.position[0])); - GL_ERROR_CHECK(glLightf(target, GL_CONSTANT_ATTENUATION, 0.0f)); - GL_ERROR_CHECK(glLightf(target, GL_LINEAR_ATTENUATION, 0)); - GL_ERROR_CHECK(glLightf(target, GL_QUADRATIC_ATTENUATION, 1.0f / info.power)); - } - for ( ; i < metadata.light.max; ++i ) GL_ERROR_CHECK(glDisable(GL_LIGHT0+i)); - } -#elif UF_USE_VULKAN +#if UF_USE_VULKAN struct UniformDescriptor { struct Matrices { alignas(16) pod::Matrix4f view; diff --git a/ext/main.cpp b/ext/main.cpp index 9a063861..e897e1c2 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -659,6 +659,9 @@ void EXT_API ext::tick() { ++::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); + #if UF_ENV_DREAMCAST + DC_STATS(); + #endif ::times.frames = 0; } } diff --git a/makefiles/dreamcast.gcc.make b/makefiles/dreamcast.gcc.make index f786fd54..3909568c 100644 --- a/makefiles/dreamcast.gcc.make +++ b/makefiles/dreamcast.gcc.make @@ -3,7 +3,7 @@ CDIR = CC = gcc CXX = $(KOS_CCPLUS) TARGET_EXTENSION = elf -OPTIMIZATIONS = -Os -fstrict-aliasing -ffast-math -flto -DUF_NO_EXCEPTIONS -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer +OPTIMIZATIONS = -Os -g -ffunction-sections -fdata-sections -Wl,--gc-sections -fstrict-aliasing -ffast-math -flto -DUF_NO_EXCEPTIONS -fno-unroll-all-loops -fno-optimize-sibling-calls -fschedule-insns2 -fomit-frame-pointer WARNINGS = -Wno-attributes -Wno-conversion-null FLAGS += $(KOS_CPPFLAGS) -std=c++17 $(OPTIMIZATIONS) $(WARNINGS) -fdiagnostics-color=always INCS += $(KOS_INC_PATHS) -I/opt/dreamcast/sh-elf/sh-elf/include diff --git a/makefiles/win64.gcc.make b/makefiles/win64.gcc.make index e25a8050..e99da8b4 100644 --- a/makefiles/win64.gcc.make +++ b/makefiles/win64.gcc.make @@ -2,6 +2,6 @@ ARCH = win64 CDIR = CC = gcc CXX = g++ -OPTIMIZATIONS = -O3 -fstrict-aliasing -flto +OPTIMIZATIONS = -O3 -g -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 \ No newline at end of file