Commit for 2022.05.09 00-07-22.7z

This commit is contained in:
mrq 2022-05-09 00:07:00 -05:00
parent c8853dc1b8
commit cf3d1eebc1
96 changed files with 1679 additions and 670 deletions

View File

@ -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)

View File

@ -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"
]
}
},

View File

@ -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,

View File

@ -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 } },

View File

@ -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;
};

View File

@ -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) );
}
}

View File

@ -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();
}

View File

@ -4,5 +4,6 @@
#define INSTANCED 1
#define SKINNED 0
#define BAKING 1
#define LAYERED 1
#include "../base.vert.h"

View File

@ -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[];
};

View File

@ -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
}

View File

@ -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[];
};

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1,12 @@
{
"behaviors": [ "SoundEmitterBehavior" ],
"metadata": {
"audio": {
"spatial": true,
"loop": true,
"volume": 1,
"rolloffFactor": 1,
"streamed": true
}
}
}

View File

@ -0,0 +1,13 @@
{
"assets": [
"./scripts/camera.lua",
"./audio/soundscape/camera.ogg"
],
"metadata": {
"audio": {
"rolloffFactor": 4,
"volume": 1.0
},
"sensitivity": 10
}
}

View File

@ -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"
}
}
}

View File

@ -0,0 +1,13 @@
{
"assets": [ "./scripts/lift.lua" ],
"system": {
"physics": {
"type": "bounding box",
"recenter": true,
"mass": 100,
"restitution": 0,
"friction": 1
}
}
}

View File

@ -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": "コマンド"
}
}
}

View File

@ -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 ] } } }
}
}
}
}

View File

@ -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
}
}

View File

@ -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]
}
}
}

View File

@ -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
}
}
}

View File

@ -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 )

View File

@ -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 )

View File

@ -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
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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<ext::vulkan::Graphic*> 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 );

View File

@ -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;

View File

@ -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:

View File

@ -5,8 +5,7 @@
#if UF_USE_XATLAS
namespace ext {
namespace xatlas {
pod::Vector2ui UF_API unwrap( uf::stl::vector<uf::graph::mesh::Skinned>& vertices, uf::stl::vector<uint32_t>& indices );
pod::Vector2ui UF_API unwrap( pod::Graph& );
size_t UF_API unwrap( pod::Graph&, bool = false );
}
}
#endif

View File

@ -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 )
#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

View File

@ -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

View File

@ -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<Event> 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<typename T> 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<typename T> void pushEvent( const uf::Hooks::name_t& name, const T& payload );
static bool focused;
};
}
}

View File

@ -3,15 +3,19 @@
#include <uf/config.h>
#include "universal.h"
#if UF_ENV_WINDOWS
#if UF_USE_VULKAN
#include <uf/ext/vulkan/vk.h>
#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

View File

@ -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();
}
}

View File

@ -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<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };

View File

@ -1,61 +1,4 @@
#pragma once
#include <uf/config.h>
#include <uf/spec/window/window.h>
#include <uf/spec/context/context.h>
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<uf::stl::string> 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;
};
}
#include <uf/spec/window/window.h>

View File

@ -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<uf::stl::string>();
/*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;
}

View File

@ -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<pod::Graph&>(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 ) {

View File

@ -10,12 +10,6 @@
#include <uf/utils/memory/map.h>
#include <uf/ext/xatlas/xatlas.h>
#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<size_t>(512);
size_t maxCubemaps = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(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<bool>() ) {
uf::stl::unordered_map<size_t, uf::stl::string> filenames;
uf::stl::unordered_map<size_t, size_t> 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::stl::string>(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<uf::stl::string>() == key;
auto filter = graph.metadata["filter"].as<uf::stl::string>() == "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<uf::Serializer>();
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<bool>() ) {
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<uf::stl::string>() == "load" ) {
if ( info["filename"].is<uf::stl::string>() ) {
if ( ext::json::isObject( info ) ) {
if ( info["ignore"].as<bool>() ) return;
if ( info["action"].as<uf::stl::string>() == "load" ) {
if ( info["filename"].is<uf::stl::string>() ) {
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
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<uf::stl::string>() == "attach" ) {
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
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<pod::Transform<>>();
auto flatten = uf::transform::flatten( node.transform );
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
}
if ( info["static"].is<bool>() ) {
metadata.system.ignoreGraph = info["static"].as<bool>();
}
} else if ( info["action"].as<uf::stl::string>() == "attach" ) {
uf::stl::string filename = uf::io::resolveURI( info["filename"].as<uf::stl::string>(), graph.metadata["root"].as<uf::stl::string>() );
auto& child = entity.loadChild( filename, false );
auto& childTransform = child.getComponent<pod::Transform<>>();
auto flatten = uf::transform::flatten( node.transform );
if ( !info["preserve position"].as<bool>() ) childTransform.position = flatten.position;
if ( !info["preserve orientation"].as<bool>() ) childTransform.orientation = flatten.orientation;
}
if ( info["static"].is<bool>() ) {
metadata.system.ignoreGraph = info["static"].as<bool>();
}
}
// 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;

View File

@ -19,6 +19,9 @@
#include <gltf/tiny_gltf.h>
#include <uf/ext/gltf/gltf.h>
#if UF_USE_XATLAS
#include <uf/ext/xatlas/xatlas.h>
#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<bool>() ) uf::graph::save( graph, filename );
if ( graph.metadata["exporter"]["enabled"].as<bool>() ) {
uf::graph::save( graph, filename );
}
return graph;
}
#endif

View File

@ -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<UF_GRAPH_MESH_FORMAT>();
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 );

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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<uint32_t>(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<float>(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();
}

View File

@ -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 ) {

View File

@ -364,6 +364,7 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
uf::stl::vector<VkDescriptorImageInfo> image;
uf::stl::vector<VkDescriptorImageInfo> image2D;
uf::stl::vector<VkDescriptorImageInfo> image2DA;
uf::stl::vector<VkDescriptorImageInfo> imageCube;
uf::stl::vector<VkDescriptorImageInfo> image3D;
uf::stl::vector<VkDescriptorImageInfo> 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(

View File

@ -41,10 +41,10 @@ uf::stl::vector<ext::vulkan::Graphic*> 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 );

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -2,38 +2,37 @@
#if UF_USE_XATLAS
#include <xatlas/xatlas.h>
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<Entry> entries;
size_t vertexOffset = 0;
};
uf::stl::vector<Pair> entries;
entries.reserve(graph.meshes.size());
uf::stl::vector<uf::Mesh> sources;
sources.reserve(graph.meshes.size());
::xatlas::Atlas* atlas = ::xatlas::Create();
uf::stl::unordered_map<size_t, Atlas> atlases;
atlases.reserve(graph.meshes.size());
uf::stl::vector<size_t> 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<size_t> 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<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(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<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas->width, vertex.uv[1] / atlas->height };
} else {
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(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<uint8_t*>(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<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(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

View File

@ -5,6 +5,9 @@
#include <uf/utils/window/payloads.h>
#include <uf/utils/io/inputs.h>
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
#include <uf/spec/context/context.h>
#if UF_ENV_DREAMCAST
/*
@ -269,14 +272,71 @@ namespace {
}
}
UF_API_CALL spec::dreamcast::Window::Window() {}
#include <dc/pvr.h>
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 <uf/utils/serialize/serializer.h>
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

View File

@ -4,6 +4,8 @@
#include <uf/utils/serialize/serializer.h>
#include <sstream>
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
}
}
#endif

View File

@ -6,6 +6,9 @@
#include <uf/utils/io/inputs.h>
#include <uf/utils/string/ext.h>
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
#include <uf/spec/context/context.h>
#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<LONG_PTR>(&::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

View File

@ -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();
}

View File

@ -1,175 +0,0 @@
#include <uf/config.h>
#if !UF_USE_SFML
#define UF_OPENGL_CONTEXT_IN_WINDOW 0
#include <uf/utils/window/window.h>
#include <uf/utils/io/iostream.h>
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::stl::string> 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 <thread>
#include <chrono>
#include <uf/utils/time/time.h>
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

View File

@ -1,5 +1,5 @@
#include <uf/config.h>
#if !UF_ENV_DREAMCAST
#if UF_USE_VULKAN
#include "behavior.h"
#include <uf/utils/renderer/renderer.h>
@ -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<uf::Graphic>() ) return;
auto& graphic = entity->getComponent<uf::Graphic>();
@ -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;

View File

@ -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;

View File

@ -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<uf::Camera>();
auto& controllerMetadata = controller.getComponent<uf::Serializer>();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
auto& metadataVxgi = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
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<LightInfo> entities;
for ( auto entity : graph ) {
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
if ( metadata.power <= 0 ) continue;
auto flatten = uf::transform::flatten( entity->getComponent<pod::Transform<>>() );
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<LightInfo> entities;
for ( auto entity : graph ) {
if ( entity == this || entity == &controller || !entity->hasComponent<ext::LightBehavior::Metadata>() ) continue;
auto& metadata = entity->getComponent<ext::LightBehavior::Metadata>();
if ( metadata.power <= 0 ) continue;
auto flatten = uf::transform::flatten( entity->getComponent<pod::Transform<>>() );
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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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