WIP: Vulkan buffers
This commit is contained in:
parent
41eb636826
commit
3cc8870037
|
@ -19,9 +19,10 @@
|
|||
namespace tracy
|
||||
{
|
||||
class VkCtxScope {};
|
||||
class VkCtx;
|
||||
}
|
||||
|
||||
using TracyVkCtx = void*;
|
||||
using TracyVkCtx = tracy::VkCtx*;
|
||||
|
||||
#else
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec4 Color;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main(){
|
||||
color = vec4(Color.xyz, .5);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#version 450 core
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 MVP;
|
||||
} Push;
|
||||
|
||||
layout(location = 0) in vec3 Position_modelspace;
|
||||
layout(location = 1) in vec4 Color_model;
|
||||
|
||||
layout(location = 0) out vec4 Color;
|
||||
|
||||
void main(){
|
||||
gl_Position = Push.MVP * vec4(Position_modelspace, 1);
|
||||
Color = Color_model;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(binding = 1) uniform samplerCube Texture;
|
||||
|
||||
layout(location = 0) in vec3 UV;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main(){
|
||||
color = texture(Texture, UV);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#version 450 core
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 View;
|
||||
mat4 Projection;
|
||||
} Push;
|
||||
|
||||
layout (location = 0) in vec3 Position_modelspace;
|
||||
|
||||
layout (location = 0) out vec3 UV;
|
||||
|
||||
void main(){
|
||||
UV = Position_modelspace;
|
||||
gl_Position = (Push.Projection * Push.View * vec4(Position_modelspace, 1.0)).xyww;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(inPosition, 0.0, 1.0);
|
||||
fragColor = inColor;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(0.0, -0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-0.5, 0.5)
|
||||
);
|
||||
|
||||
vec3 colors[3] = vec3[](
|
||||
vec3(1.0, 0.0, 0.0),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
fragColor = colors[gl_VertexIndex];
|
||||
}
|
|
@ -1,27 +1,39 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (constant_id = 0) const bool FOG = true;
|
||||
layout (constant_id = 1) const bool PBR = true;
|
||||
layout (constant_id = 2) const bool TRIPLANAR = false;
|
||||
layout (constant_id = 3) const bool STOCHASTIC = false;
|
||||
layout (constant_id = 4) const bool BLEND = true;
|
||||
// ...
|
||||
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
||||
|
||||
layout (constant_id = 16) UNIT_SIZE = 8;
|
||||
layout (binding = 1) uniform sampler2DArray TextureAtlas;
|
||||
layout (binding = 2) uniform sampler2DArray NormalAtlas;
|
||||
layout (binding = 3) uniform sampler2DArray HOSAtlas;
|
||||
|
||||
// Ouput data
|
||||
layout(location = 0) out vec3 color;
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 Proj;
|
||||
mat4 View;
|
||||
#ifndef INSTANCED
|
||||
mat4 Model;
|
||||
#endif
|
||||
|
||||
uniform sampler2DArray TextureAtlas;
|
||||
uniform sampler2DArray NormalAtlas;
|
||||
uniform sampler2DArray HOSAtlas;
|
||||
vec4 SphereProj;
|
||||
float Curvature;
|
||||
|
||||
uniform mat4 View;
|
||||
uniform vec3 FogColor;
|
||||
//MAYBE: extract
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} Push;
|
||||
|
||||
#ifdef GEOMETRY
|
||||
in GeometryData
|
||||
layout (location = 0) in GeometryData
|
||||
#else
|
||||
in VertexData
|
||||
layout (location = 0) in VertexData
|
||||
#endif
|
||||
{
|
||||
vec3 Position_modelspace;
|
||||
|
@ -40,6 +52,8 @@ in VertexData
|
|||
float Depth;
|
||||
} vs;
|
||||
|
||||
layout(location = 0) out vec3 color;
|
||||
|
||||
vec3 expand(vec3 v) {
|
||||
return (v - 0.5) * 2;
|
||||
}
|
||||
|
@ -49,7 +63,7 @@ vec2 hash2D(vec2 s) {
|
|||
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
|
||||
}
|
||||
|
||||
vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
|
||||
vec4 textureStochastic(sampler2DArray smpl, vec3 UV) {
|
||||
if(STOCHASTIC) {
|
||||
// triangular by approx 2*sqrt(3)
|
||||
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
||||
|
@ -79,46 +93,48 @@ if(STOCHASTIC) {
|
|||
vec2 dx = dFdx(UV.xy);
|
||||
vec2 dy = dFdy(UV.xy);
|
||||
|
||||
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
||||
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
||||
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
||||
return textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
||||
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
|
||||
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
||||
} else {
|
||||
return texture(sample, UV);
|
||||
return texture(smpl, UV);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 getTexture(sampler2DArray sample, vec2 UV) {
|
||||
vec4 getTexture(sampler2DArray smpl, vec2 UV) {
|
||||
#ifdef GEOMETRY
|
||||
if(BLEND) {
|
||||
vec4 colx = textureStochastic(sample, vec3(UV, vs.Textures[0]));
|
||||
vec4 colx = textureStochastic(smpl, vec3(UV, vs.Textures[0]));
|
||||
if(vs.Textures[1] == vs.Textures[0]) {
|
||||
return vs.Textures[2] == vs.Textures[0] ? colx :
|
||||
mix(colx, textureStochastic(sample, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
|
||||
mix(colx, textureStochastic(smpl, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
|
||||
} else {
|
||||
vec4 coly = textureStochastic(sample, vec3(UV, vs.Textures[1]));
|
||||
vec4 coly = textureStochastic(smpl, vec3(UV, vs.Textures[1]));
|
||||
return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : (
|
||||
vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) :
|
||||
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochastic(sample, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
|
||||
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochastic(smpl, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
|
||||
}
|
||||
} else {
|
||||
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
|
||||
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
|
||||
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2);
|
||||
return textureStochastic(sample, vec3(UV, vs.Textures[mainTexture]));
|
||||
return textureStochastic(smpl, vec3(UV, vs.Textures[mainTexture]));
|
||||
}
|
||||
#else
|
||||
return textureStochastic(sample, vec3(UV, vs.Texture));
|
||||
return textureStochastic(smpl, vec3(UV, vs.Texture));
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
||||
return getTexture(sample, crdx).rgb * weights.x +
|
||||
getTexture(sample, crdy).rgb * weights.y +
|
||||
getTexture(sample, crdz).rgb * weights.z;
|
||||
vec3 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
||||
return getTexture(smpl, crdx).rgb * weights.x +
|
||||
getTexture(smpl, crdy).rgb * weights.y +
|
||||
getTexture(smpl, crdz).rgb * weights.z;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float texScale = 1. / UNIT_SIZE;
|
||||
vec3 tex, texN, worldNormal, texHOS;
|
||||
|
||||
if(TRIPLANAR) {
|
||||
// Triplanar
|
||||
float plateauSize = 0.001;
|
||||
|
@ -173,7 +189,7 @@ if(PBR) {
|
|||
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
|
||||
vec3 TextureSpecularColor = vec3(.8) * texHOS.z;
|
||||
|
||||
vec3 Normal_cameraspace = normalize((View * vec4(worldNormal,0)).xyz);
|
||||
vec3 Normal_cameraspace = normalize((Push.View * vec4(worldNormal,0)).xyz);
|
||||
|
||||
// Light emission properties
|
||||
// You probably want to put them as uniforms
|
||||
|
@ -218,7 +234,7 @@ if(PBR) {
|
|||
}
|
||||
if(FOG) {
|
||||
float ratio = exp(vs.Depth * 0.69)-1;
|
||||
color = mix(color, pow(FogColor, vec3(2.2)), clamp(ratio, 0, 1));
|
||||
color = mix(color, pow(Push.FogColor, vec3(2.2)), clamp(ratio, 0, 1));
|
||||
}
|
||||
color = pow(color, vec3(1.0 / 2.2));
|
||||
if(color.r > 1 || color.g > 1 || color.b > 1) {
|
|
@ -1,4 +1,5 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (constant_id = 0) const bool FOG = true;
|
||||
layout (constant_id = 1) const bool PBR = true;
|
||||
|
@ -6,7 +7,7 @@ layout (constant_id = 1) const bool PBR = true;
|
|||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 3) out;
|
||||
|
||||
in VertexData {
|
||||
layout (location = 0) in VertexData {
|
||||
vec3 Position_modelspace;
|
||||
flat uint Texture;
|
||||
vec3 FaceNormal_modelspace;
|
||||
|
@ -18,7 +19,7 @@ in VertexData {
|
|||
float Depth;
|
||||
} vs_in[];
|
||||
|
||||
out GeometryData {
|
||||
layout (location = 0) out GeometryData {
|
||||
vec3 Position_modelspace;
|
||||
flat uint Textures[3];
|
||||
vec3 TextureRatio;
|
|
@ -1,4 +1,5 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (constant_id = 0) const bool FOG = true;
|
||||
layout (constant_id = 1) const bool PBR = true;
|
||||
|
@ -6,11 +7,32 @@ layout (constant_id = 1) const bool PBR = true;
|
|||
layout (constant_id = 5) const bool DO_CURVATURE = false;
|
||||
layout (constant_id = 6) const bool CURV_DEPTH = true;
|
||||
|
||||
layout(location = 0) in vec3 Position_modelspace;
|
||||
layout(location = 1) in uint Texture_model;
|
||||
layout(location = 2) in vec3 Normal_modelspace;
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 Proj;
|
||||
mat4 View;
|
||||
#ifndef INSTANCED
|
||||
mat4 Model;
|
||||
#endif
|
||||
|
||||
out VertexData {
|
||||
vec4 SphereProj;
|
||||
float Curvature;
|
||||
|
||||
//MAYBE: extract
|
||||
vec3 FogColor;
|
||||
float FogDepth;
|
||||
|
||||
vec3 LightInvDirection_worldspace;
|
||||
} Push;
|
||||
|
||||
layout (location = 0) in vec3 Position_modelspace;
|
||||
layout (location = 1) in uint Texture_model;
|
||||
layout (location = 2) in vec3 Normal_modelspace;
|
||||
|
||||
#ifdef INSTANCED
|
||||
layout (location = 6) in mat4 Model;
|
||||
#endif
|
||||
|
||||
layout (location = 0) out VertexData {
|
||||
vec3 Position_modelspace;
|
||||
flat uint Texture;
|
||||
vec3 FaceNormal_modelspace;
|
||||
|
@ -22,47 +44,35 @@ out VertexData {
|
|||
float Depth;
|
||||
} vs;
|
||||
|
||||
#ifdef INSTANCED
|
||||
layout(location = 6) in mat4 Model;
|
||||
#else
|
||||
uniform mat4 Model;
|
||||
#endif
|
||||
uniform mat4 View;
|
||||
uniform mat4 Proj;
|
||||
|
||||
uniform vec4 SphereProj;
|
||||
uniform float Curvature;
|
||||
|
||||
uniform vec3 LightInvDirection_worldspace;
|
||||
uniform float FogDepth;
|
||||
|
||||
void main(){
|
||||
#ifndef INSTANCED
|
||||
mat4 Model = Push.Model;
|
||||
#endif
|
||||
|
||||
vs.Position_modelspace = Position_modelspace;
|
||||
|
||||
if(DO_CURVATURE) {
|
||||
if(Curvature > 0) {
|
||||
vec3 Position_areaspace = Position_modelspace + SphereProj.xyz;
|
||||
if(Push.Curvature > 0) {
|
||||
vec3 Position_areaspace = Position_modelspace + Push.SphereProj.xyz;
|
||||
vec2 sph = vec2(acos(Position_areaspace.z / length(Position_areaspace.xyz)), atan(Position_areaspace.y, Position_areaspace.x));
|
||||
if(CURV_DEPTH) {
|
||||
float radius = max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z));
|
||||
} else {
|
||||
float radius = SphereProj.w;
|
||||
}
|
||||
vs.Position_modelspace = mix(vs.Position_modelspace, vec3(sin(sph.x)*cos(sph.y), sin(sph.x)*sin(sph.y), cos(sph.x)) * radius - SphereProj.xyz, Curvature);
|
||||
float radius = CURV_DEPTH ?
|
||||
max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z)) :
|
||||
Push.SphereProj.w;
|
||||
vs.Position_modelspace = mix(vs.Position_modelspace, vec3(sin(sph.x)*cos(sph.y), sin(sph.x)*sin(sph.y), cos(sph.x)) * radius - Push.SphereProj.xyz, Push.Curvature);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 Position_cameraspace = View * Model * vec4(vs.Position_modelspace, 1);
|
||||
gl_Position = Proj * Position_cameraspace;
|
||||
vec4 Position_cameraspace = Push.View * Model * vec4(vs.Position_modelspace, 1);
|
||||
gl_Position = Push.Proj * Position_cameraspace;
|
||||
|
||||
if(FOG) {
|
||||
vs.Depth = length(Position_cameraspace.xyz) / FogDepth;
|
||||
vs.Depth = length(Position_cameraspace.xyz) / Push.FogDepth;
|
||||
}
|
||||
|
||||
vs.Texture = Texture_model;
|
||||
|
||||
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
|
||||
if(PBR)
|
||||
if(PBR) {
|
||||
// TODO: correct normal curvature
|
||||
vs.FaceNormal_worldspace = normalize((Model * vec4(vs.FaceNormal_modelspace, 0)).xyz);
|
||||
|
||||
|
@ -71,6 +81,6 @@ if(PBR)
|
|||
vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz;
|
||||
|
||||
// Vector that goes from the vertex to the light, in camera space
|
||||
vs.LightDirection_cameraspace = (View * vec4(LightInvDirection_worldspace,0)).xyz;
|
||||
vs.LightDirection_cameraspace = (Push.View * vec4(Push.LightInvDirection_worldspace,0)).xyz;
|
||||
}
|
||||
}
|
|
@ -2,28 +2,32 @@
|
|||
|
||||
BASEDIR=$(dirname "$0")
|
||||
TARGETDIR="$BASEDIR/../content/shaders"
|
||||
GLSL="glslc"
|
||||
|
||||
rm $TARGETDIR/*.spv
|
||||
|
||||
# Tris
|
||||
glslc -fshader-stage=vertex $BASEDIR/Tris.vs -o $TARGETDIR/Tris.vs.spv
|
||||
glslc -fshader-stage=fragment $BASEDIR/Tris.fs -o $TARGETDIR/Tris.fs.spv
|
||||
$GLSL $BASEDIR/Tris.vert -o $TARGETDIR/Tris.vs.spv
|
||||
$GLSL $BASEDIR/Tris.frag -o $TARGETDIR/Tris.fs.spv
|
||||
$GLSL $BASEDIR/Tris.vert $BASEDIR/Tris.frag -o $TARGETDIR/Tris.spv
|
||||
|
||||
# Color
|
||||
glslc -fshader-stage=vertex $TARGETDIR/Color.vs -o $TARGETDIR/Color.vs.spv
|
||||
glslc -fshader-stage=fragment $TARGETDIR/Color.fs -o $TARGETDIR/Color.fs.spv
|
||||
$GLSL $BASEDIR/Color.vert -o $TARGETDIR/Color.vs.spv
|
||||
$GLSL $BASEDIR/Color.frag -o $TARGETDIR/Color.fs.spv
|
||||
|
||||
# Sky
|
||||
glslc -fshader-stage=vertex $TARGETDIR/Sky.vs -o $TARGETDIR/Sky.vs.spv
|
||||
glslc -fshader-stage=fragment $TARGETDIR/Sky.fs -o $TARGETDIR/Sky.fs.spv
|
||||
$GLSL $BASEDIR/Sky.vert -o $TARGETDIR/Sky.vs.spv
|
||||
$GLSL $BASEDIR/Sky.frag -o $TARGETDIR/Sky.fs.spv
|
||||
|
||||
# Voxel
|
||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -o $TARGETDIR/Voxel.vs.spv
|
||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -o $TARGETDIR/Voxel.fs.spv
|
||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
|
||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DINSTANCED -o $TARGETDIR/Voxel.fs.ins.spv
|
||||
$GLSL $BASEDIR/Voxel.vert -o $TARGETDIR/Voxel.vs.spv
|
||||
$GLSL $BASEDIR/Voxel.frag -o $TARGETDIR/Voxel.fs.spv
|
||||
$GLSL $BASEDIR/Voxel.vert -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
|
||||
$GLSL $BASEDIR/Voxel.frag -DINSTANCED -o $TARGETDIR/Voxel.fs.ins.spv
|
||||
|
||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DGEOMETRY -o $TARGETDIR/Voxel.vs.geo.spv
|
||||
glslc -fshader-stage=geometry $BASEDIR/Voxel.gs -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
|
||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
|
||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.vs.geo.ins.spv
|
||||
glslc -fshader-stage=geometry $BASEDIR/Voxel.gs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.gs.geo.ins.spv
|
||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.fs.geo.ins.spv
|
||||
$GLSL $BASEDIR/Voxel.vert -DGEOMETRY -o $TARGETDIR/Voxel.vs.geo.spv
|
||||
$GLSL $BASEDIR/Voxel.geom -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
|
||||
$GLSL $BASEDIR/Voxel.frag -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
|
||||
$GLSL $BASEDIR/Voxel.vert -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.vs.geo.ins.spv
|
||||
$GLSL $BASEDIR/Voxel.geom -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.gs.geo.ins.spv
|
||||
$GLSL $BASEDIR/Voxel.frag -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.fs.geo.ins.spv
|
|
@ -35,6 +35,7 @@ void Client::run(server_handle* const localHandle) {
|
|||
//TODO: loop
|
||||
do {
|
||||
window.startFrame();
|
||||
FrameMark;
|
||||
{ // Update
|
||||
ZoneScopedN("Update");
|
||||
static double lastTime = window.getTime();
|
||||
|
@ -178,7 +179,6 @@ void Client::run(server_handle* const localHandle) {
|
|||
ZoneScopedN("Swap");
|
||||
pipeline->swapBuffer(window);
|
||||
inputs.poll();
|
||||
FrameMarkNamed("Client");
|
||||
}
|
||||
|
||||
window.waitTargetFPS();
|
||||
|
|
|
@ -183,8 +183,16 @@ namespace contouring {
|
|||
}
|
||||
|
||||
void FlatDualMC::onGui() {
|
||||
ImGui::SliderInt("Load Distance", &loadDistance, 1, keepDistance);
|
||||
ImGui::SliderInt("Keep Distance", &keepDistance, loadDistance + 1, 21);
|
||||
{
|
||||
int load = loadDistance;
|
||||
ImGui::SliderInt("Load Distance", &load, 1, keepDistance);
|
||||
loadDistance = load;
|
||||
}
|
||||
{
|
||||
int keep = keepDistance;
|
||||
ImGui::SliderInt("Keep Distance", &keep, loadDistance + 1, 21);
|
||||
keepDistance = keep;
|
||||
}
|
||||
ImGui::Checkbox("Transparency", &transparency);
|
||||
ImGui::SliderFloat("Iso", &iso, 0, 1);
|
||||
ImGui::Checkbox("Manifold", &manifold);
|
||||
|
|
|
@ -49,8 +49,8 @@ namespace contouring {
|
|||
|
||||
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
|
||||
|
||||
int loadDistance = 3;
|
||||
int keepDistance = 4;
|
||||
ushort loadDistance = 3;
|
||||
ushort keepDistance = 4;
|
||||
bool transparency = false;
|
||||
float iso = .1f;
|
||||
bool manifold = true;
|
||||
|
|
|
@ -114,8 +114,12 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
|||
|
||||
if (options.debugMenu.world) {
|
||||
ImGui::Begin("Debug: World", &options.debugMenu.world, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
|
||||
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
|
||||
int load = options.world.loadDistance;
|
||||
int keep = options.world.keepDistance;
|
||||
if (ImGui::SliderInt("Load distance", &load, 1, options.world.keepDistance) |
|
||||
ImGui::SliderInt("Keep distance", &keep, options.world.loadDistance + 1, 21)) {
|
||||
options.world.loadDistance = load;
|
||||
options.world.keepDistance = keep;
|
||||
actions |= Actions::World;
|
||||
}
|
||||
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {
|
||||
|
|
|
@ -1,31 +1,81 @@
|
|||
#include "CommandPool.hpp"
|
||||
|
||||
#include "shared.hpp"
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include <TracyVulkan.hpp>
|
||||
#include "buffer/VertexData.hpp"
|
||||
#include <memory.h>
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
CommandPool::CommandPool(VkDevice device, const std::vector<VkImageView>& views, PipelineRef pipe, const PhysicalDeviceInfo& info, const renderOptions& opt):
|
||||
device(device) {
|
||||
CommandPool::CommandPool(VkDevice device, const std::vector<VkImageView> &views, PipelineRef pipe, const PhysicalDeviceInfo &info, const renderOptions &opt,
|
||||
VkQueue ctxQueue) : device(device)
|
||||
{
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
|
||||
poolInfo.flags = 0; // Optional
|
||||
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // Optional
|
||||
|
||||
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
|
||||
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &cmdPool) != VK_SUCCESS) {
|
||||
FATAL("Failed to create command pool!");
|
||||
}
|
||||
|
||||
allocate(views, pipe, info.swapDetails.capabilities.currentExtent, opt);
|
||||
{
|
||||
size_t size = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size();
|
||||
createAllocatedBuffer(info, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
vertexBuffer, vertexBufferMemory);
|
||||
|
||||
// Upload
|
||||
void* data;
|
||||
vkMapMemory(device, vertexBufferMemory, 0, size, 0, &data);
|
||||
memcpy(data, buffer::vk::vertices.data(), size);
|
||||
vkUnmapMemory(device, vertexBufferMemory);
|
||||
|
||||
/*
|
||||
VkBuffer stagingBuffer;
|
||||
VkDeviceMemory stagingBufferMemory;
|
||||
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
|
||||
|
||||
void* data;
|
||||
vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||
memcpy(data, vertices.data(), (size_t) bufferSize);
|
||||
vkUnmapMemory(device, stagingBufferMemory);
|
||||
|
||||
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
|
||||
|
||||
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
|
||||
*/
|
||||
}
|
||||
{
|
||||
size_t size = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size();
|
||||
createAllocatedBuffer(info, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
indexBuffer, indexBufferMemory);
|
||||
|
||||
// Upload
|
||||
void* data;
|
||||
vkMapMemory(device, indexBufferMemory, 0, size, 0, &data);
|
||||
memcpy(data, buffer::vk::indices.data(), size);
|
||||
vkUnmapMemory(device, indexBufferMemory);
|
||||
}
|
||||
|
||||
allocate(views, pipe, info.swapDetails.capabilities.currentExtent, opt, info.device, device, ctxQueue);
|
||||
}
|
||||
CommandPool::~CommandPool() {
|
||||
if(!freed)
|
||||
free();
|
||||
|
||||
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
||||
vkDestroyBuffer(device, indexBuffer, ALLOC);
|
||||
vkFreeMemory(device, indexBufferMemory, ALLOC);
|
||||
|
||||
vkDestroyBuffer(device, vertexBuffer, ALLOC);
|
||||
vkFreeMemory(device, vertexBufferMemory, ALLOC);
|
||||
|
||||
vkDestroyCommandPool(device, cmdPool, ALLOC);
|
||||
}
|
||||
void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, VkExtent2D extent, const renderOptions& opt) {
|
||||
void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, VkExtent2D extent, const renderOptions& opt,
|
||||
VkPhysicalDevice phyDevice, VkDevice device, VkQueue ctxQueue)
|
||||
{
|
||||
assert(freed);
|
||||
|
||||
framebuffers.resize(views.size());
|
||||
|
@ -47,25 +97,28 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
|
|||
}
|
||||
}
|
||||
|
||||
graphicsBuffers.resize(framebuffers.size());
|
||||
cmdBuffers.resize(framebuffers.size());
|
||||
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.commandPool = graphicsPool;
|
||||
allocInfo.commandPool = cmdPool;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandBufferCount = (uint32_t) graphicsBuffers.size();
|
||||
allocInfo.commandBufferCount = (uint32_t) cmdBuffers.size();
|
||||
|
||||
if (vkAllocateCommandBuffers(device, &allocInfo, graphicsBuffers.data()) != VK_SUCCESS) {
|
||||
if (vkAllocateCommandBuffers(device, &allocInfo, cmdBuffers.data()) != VK_SUCCESS) {
|
||||
FATAL("Failed to allocate command buffers!");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < graphicsBuffers.size(); i++) {
|
||||
tracyCtx.resize(cmdBuffers.size());
|
||||
for (size_t i = 0; i < cmdBuffers.size(); i++) {
|
||||
tracyCtx[i] = TracyVkContext(phyDevice, device, ctxQueue, cmdBuffers[i]);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = 0;
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
|
||||
if (vkBeginCommandBuffer(graphicsBuffers[i], &beginInfo) != VK_SUCCESS) {
|
||||
if (vkBeginCommandBuffer(cmdBuffers[i], &beginInfo) != VK_SUCCESS) {
|
||||
FATAL("Failed to begin recording command buffer!");
|
||||
}
|
||||
|
||||
|
@ -80,12 +133,16 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
|
|||
renderPassInfo.clearValueCount = 1; //TODO: clear depth
|
||||
renderPassInfo.pClearValues = &clearColor;
|
||||
|
||||
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
|
||||
vkCmdDraw(graphicsBuffers[i], 3, 1, 0, 0);
|
||||
vkCmdEndRenderPass(graphicsBuffers[i]);
|
||||
vkCmdBeginRenderPass(cmdBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
|
||||
VkBuffer vertexBuffers[] = {vertexBuffer};
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(cmdBuffers[i], 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(cmdBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);
|
||||
vkCmdDrawIndexed(cmdBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
|
||||
vkCmdEndRenderPass(cmdBuffers[i]);
|
||||
|
||||
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
|
||||
if (vkEndCommandBuffer(cmdBuffers[i]) != VK_SUCCESS) {
|
||||
FATAL("Failed to record command buffer!");
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +155,12 @@ void CommandPool::free() {
|
|||
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
|
||||
}
|
||||
|
||||
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
|
||||
#if TRACY_ENABLE
|
||||
for (auto ctx : tracyCtx) {
|
||||
TracyVkDestroy(ctx);
|
||||
}
|
||||
#endif
|
||||
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(cmdBuffers.size()), cmdBuffers.data());
|
||||
|
||||
freed = true;
|
||||
}
|
||||
|
@ -106,6 +168,9 @@ void CommandPool::free() {
|
|||
void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
||||
assert(!freed);
|
||||
|
||||
TracyVkCollect(tracyCtx[idx], cmdBuffers[idx]);
|
||||
//TracyVkZone(tracyCtx[idx], graphicsBuffers[idx], "Submit");
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
|
@ -116,7 +181,7 @@ void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphor
|
|||
submitInfo.pWaitDstStageMask = waitStages;
|
||||
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &graphicsBuffers[idx];
|
||||
submitInfo.pCommandBuffers = &cmdBuffers[idx];
|
||||
|
||||
VkSemaphore signalSemaphores[] = {signalSemaphore};
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
|
@ -126,4 +191,69 @@ void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphor
|
|||
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, submittedFence) != VK_SUCCESS) {
|
||||
FATAL("Failed to submit draw command buffer!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandPool::createAllocatedBuffer(const PhysicalDeviceInfo& info, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
|
||||
VkBufferCreateInfo bufferInfo{};
|
||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
bufferInfo.size = size;
|
||||
bufferInfo.usage = usage;
|
||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
if (vkCreateBuffer(device, &bufferInfo, ALLOC, &buffer) != VK_SUCCESS) {
|
||||
FATAL("Failed to create buffer!");
|
||||
}
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
if (const auto memIdx = info.findMemory(memRequirements.memoryTypeBits, properties)) {
|
||||
allocInfo.memoryTypeIndex = memIdx.value();
|
||||
} else {
|
||||
FATAL("No available memory heap");
|
||||
}
|
||||
|
||||
if (vkAllocateMemory(device, &allocInfo, ALLOC, &bufferMemory) != VK_SUCCESS) {
|
||||
FATAL("Failed to allocate buffer memory!");
|
||||
}
|
||||
|
||||
vkBindBufferMemory(device, buffer, bufferMemory, 0);
|
||||
}
|
||||
|
||||
/*void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandPool = commandPool;
|
||||
allocInfo.commandBufferCount = 1;
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
|
||||
VkBufferCopy copyRegion{};
|
||||
copyRegion.srcOffset = 0; // Optional
|
||||
copyRegion.dstOffset = 0; // Optional
|
||||
copyRegion.size = size;
|
||||
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
|
||||
|
||||
vkEndCommandBuffer(commandBuffer);
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commandBuffer;
|
||||
|
||||
vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(graphicsQueue);
|
||||
|
||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
||||
}*/
|
|
@ -3,27 +3,40 @@
|
|||
#include "forward.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace tracy {
|
||||
class VkCtx;
|
||||
}
|
||||
typedef tracy::VkCtx* TracyVkCtx;
|
||||
namespace render::vk {
|
||||
class SwapChain;
|
||||
class Pipeline;
|
||||
|
||||
class CommandPool {
|
||||
public:
|
||||
CommandPool(VkDevice, const std::vector<VkImageView>&, PipelineRef, const PhysicalDeviceInfo&, const renderOptions&);
|
||||
CommandPool(VkDevice, const std::vector<VkImageView>&, PipelineRef, const PhysicalDeviceInfo&, const renderOptions&, VkQueue);
|
||||
~CommandPool();
|
||||
|
||||
void submitGraphics(uint32_t, VkQueue, VkSemaphore, VkSemaphore, VkFence);
|
||||
|
||||
void allocate(const std::vector<VkImageView>&, PipelineRef, VkExtent2D, const renderOptions&);
|
||||
void allocate(const std::vector<VkImageView> &, PipelineRef, VkExtent2D, const renderOptions &, VkPhysicalDevice, VkDevice, VkQueue);
|
||||
void free();
|
||||
|
||||
void createAllocatedBuffer(const PhysicalDeviceInfo&, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags, VkBuffer&, VkDeviceMemory&);
|
||||
|
||||
private:
|
||||
VkDevice device;
|
||||
|
||||
std::vector<VkFramebuffer> framebuffers;
|
||||
|
||||
VkCommandPool graphicsPool;
|
||||
std::vector<VkCommandBuffer> graphicsBuffers;
|
||||
VkCommandPool cmdPool;
|
||||
std::vector<VkCommandBuffer> cmdBuffers;
|
||||
std::vector<TracyVkCtx> tracyCtx;
|
||||
|
||||
VkBuffer vertexBuffer;
|
||||
VkDeviceMemory vertexBufferMemory;
|
||||
VkBuffer indexBuffer;
|
||||
VkDeviceMemory indexBufferMemory;
|
||||
|
||||
bool freed = true;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
#include "PhysicalDeviceInfo.hpp"
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
SwapChainSupportDetails SwapChainSupportDetails::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
|
||||
SwapChainSupportDetails swapDetails;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapDetails.capabilities);
|
||||
|
||||
uint32_t formatCount;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
|
||||
if (formatCount != 0) {
|
||||
swapDetails.formats.resize(formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapDetails.formats.data());
|
||||
}
|
||||
|
||||
uint32_t presentModeCount;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
|
||||
if (presentModeCount != 0) {
|
||||
swapDetails.presentModes.resize(presentModeCount);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapDetails.presentModes.data());
|
||||
}
|
||||
return swapDetails;
|
||||
}
|
||||
|
||||
QueueFamilyIndices QueueFamilyIndices::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
|
||||
QueueFamilyIndices queueIndices;
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||
|
||||
int i = 0;
|
||||
for(const auto& queueFamily: queueFamilies) {
|
||||
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
queueIndices.graphicsFamily = i;
|
||||
} else if (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) {
|
||||
queueIndices.transferFamily = i;
|
||||
}
|
||||
VkBool32 presentSupport = false;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
|
||||
if (presentSupport) {
|
||||
queueIndices.presentFamily = i;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
LOG_D("Queue " << i << ' ' << (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT ? "graphics " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT ? "compute " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT ? "transfer " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_PROTECTED_BIT ? "protected " : "")
|
||||
<< 'x' << queueFamily.queueCount);
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
|
||||
return queueIndices;
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR PhysicalDeviceInfo::getFormat() const {
|
||||
for(const auto& format: swapDetails.formats) {
|
||||
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_W("Using suboptimal surface format");
|
||||
return swapDetails.formats[0];
|
||||
}
|
||||
|
||||
std::optional<uint32_t> PhysicalDeviceInfo::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags properties) const {
|
||||
#if DEBUG
|
||||
LOG_D("available memory:");
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||
LOG_D('\t' << i << ": " << ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ? "local " : "")
|
||||
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ? "visible " : "")
|
||||
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) ? "coherent " : "")
|
||||
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) ? "cached " : "")
|
||||
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) ? "lazy " : "")
|
||||
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) ? "protected " : "")
|
||||
<< memProperties.memoryHeaps[memProperties.memoryTypes[i].heapIndex].size);
|
||||
}
|
||||
#endif
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
|
@ -17,15 +17,29 @@ struct SwapChainSupportDetails {
|
|||
struct QueueFamilyIndices {
|
||||
std::optional<uint32_t> graphicsFamily;
|
||||
std::optional<uint32_t> presentFamily;
|
||||
std::optional<uint32_t> transferFamily;
|
||||
static QueueFamilyIndices Query(VkPhysicalDevice, VkSurfaceKHR);
|
||||
bool isComplete() const { return graphicsFamily.has_value() && presentFamily.has_value(); }
|
||||
bool isOptimal() const { return isComplete() && transferFamily.has_value(); }
|
||||
};
|
||||
struct PhysicalDeviceInfo {
|
||||
VkPhysicalDevice device = VK_NULL_HANDLE;
|
||||
PhysicalDeviceInfo() {}
|
||||
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface):
|
||||
window(window), device(device), surface(surface),
|
||||
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface))
|
||||
{
|
||||
vkGetPhysicalDeviceMemoryProperties(device, &memProperties);
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR getFormat() const;
|
||||
std::optional<uint32_t> findMemory(uint32_t, VkMemoryPropertyFlags) const;
|
||||
|
||||
GLFWwindow *window;
|
||||
VkPhysicalDevice device = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface;
|
||||
SwapChainSupportDetails swapDetails;
|
||||
QueueFamilyIndices queueIndices;
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
VkSurfaceKHR surface;
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
//MAYBE: add limits memory infos
|
||||
};
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
#include "Pipeline.hpp"
|
||||
|
||||
#include "shared.hpp"
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
#include "../../../core/data/file.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "buffer/VertexData.hpp"
|
||||
|
||||
#define CONTENT_DIR "content/"
|
||||
#define SHADER_DIR CONTENT_DIR "shaders/"
|
||||
|
@ -15,7 +16,7 @@ using namespace render::vk;
|
|||
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
|
||||
{ // Render pass
|
||||
VkAttachmentDescription colorAttachment{};
|
||||
colorAttachment.format = info.surfaceFormat.format;
|
||||
colorAttachment.format = info.getFormat().format;
|
||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
|
@ -110,10 +111,13 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
|||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
||||
vertexInputInfo.pVertexBindingDescriptions = nullptr; // TODO: uniforms, and buffers
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
||||
vertexInputInfo.pVertexAttributeDescriptions = nullptr; // TODO: uniforms, and buffers
|
||||
|
||||
auto bindingDescription = buffer::vk::VertexData::getBindingDescription();
|
||||
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||
auto attributeDescriptions = buffer::vk::VertexData::getAttributeDescriptions();
|
||||
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "UI.hpp"
|
||||
#include "../../Window.hpp"
|
||||
#include "shared.hpp"
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
#include "SwapChain.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
#include "CommandPool.hpp"
|
||||
|
@ -23,22 +23,14 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf
|
|||
physicalInfo(std::make_unique<PhysicalDeviceInfo>(info)) {
|
||||
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
|
||||
vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue);
|
||||
if(info.queueIndices.transferFamily.has_value())
|
||||
vkGetDeviceQueue(device, info.queueIndices.transferFamily.value(), 0, &transferQueue.value());
|
||||
|
||||
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
||||
physicalInfo->surfaceFormat = [&]() {
|
||||
for(const auto& format: info.swapDetails.formats) {
|
||||
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_W("Using suboptimal surface format");
|
||||
return info.swapDetails.formats[0];
|
||||
}();
|
||||
|
||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||
commandPool = std::make_unique<CommandPool>(device, swapChain->getImageViews(), pipeline->getRef(), *physicalInfo.get(), options);
|
||||
commandPool = std::make_unique<CommandPool>(device, swapChain->getImageViews(), pipeline->getRef(), *physicalInfo.get(), options, graphicsQueue);
|
||||
|
||||
{
|
||||
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
||||
|
@ -81,7 +73,6 @@ Renderer::~Renderer() {
|
|||
}
|
||||
|
||||
void Renderer::recreateSwapChain() {
|
||||
LOG_D("Recreating swapchain");
|
||||
vkDeviceWaitIdle(device);
|
||||
destroySwapChain();
|
||||
|
||||
|
@ -89,7 +80,8 @@ void Renderer::recreateSwapChain() {
|
|||
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||
commandPool->allocate(swapChain->getImageViews(), pipeline->getRef(), physicalInfo->swapDetails.capabilities.currentExtent, options);
|
||||
commandPool->allocate(swapChain->getImageViews(), pipeline->getRef(), physicalInfo->swapDetails.capabilities.currentExtent, options,
|
||||
physicalInfo->device, device, graphicsQueue);
|
||||
}
|
||||
void Renderer::destroySwapChain() {
|
||||
commandPool->free();
|
||||
|
@ -266,12 +258,11 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
|||
score += deviceProperties.limits.maxImageDimension2D;
|
||||
//TODO: check others limits
|
||||
|
||||
auto infos = PhysicalDeviceInfo{device, window.getPtr(),
|
||||
SwapChainSupportDetails::Query(device, surface), QueueFamilyIndices::Query(device, surface),
|
||||
VkSurfaceFormatKHR(), surface};
|
||||
|
||||
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface);
|
||||
if (!infos.queueIndices.isComplete())
|
||||
continue;
|
||||
if (infos.queueIndices.isOptimal())
|
||||
score += 5000;
|
||||
|
||||
if (!infos.swapDetails.isValid())
|
||||
continue;
|
||||
|
@ -339,57 +330,6 @@ void Renderer::loadUI(Window& w) {
|
|||
UI::Load(w);
|
||||
}
|
||||
|
||||
SwapChainSupportDetails SwapChainSupportDetails::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
|
||||
SwapChainSupportDetails swapDetails;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapDetails.capabilities);
|
||||
|
||||
uint32_t formatCount;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
|
||||
if (formatCount != 0) {
|
||||
swapDetails.formats.resize(formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapDetails.formats.data());
|
||||
}
|
||||
|
||||
uint32_t presentModeCount;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
|
||||
if (presentModeCount != 0) {
|
||||
swapDetails.presentModes.resize(presentModeCount);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapDetails.presentModes.data());
|
||||
}
|
||||
return swapDetails;
|
||||
}
|
||||
|
||||
QueueFamilyIndices QueueFamilyIndices::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
|
||||
QueueFamilyIndices queueIndices;
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||
|
||||
int i = 0;
|
||||
for(const auto& queueFamily: queueFamilies) {
|
||||
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
queueIndices.graphicsFamily = i;
|
||||
}
|
||||
VkBool32 presentSupport = false;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
|
||||
if (presentSupport) {
|
||||
queueIndices.presentFamily = i;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
LOG_D("Queue " << i << ' ' << (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT ? "graphics " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT ? "compute " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT ? "transfer " : "")
|
||||
<< (queueFamily.queueFlags & VK_QUEUE_PROTECTED_BIT ? "protected " : "")
|
||||
<< 'x' << queueFamily.queueCount);
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
|
||||
return queueIndices;
|
||||
}
|
||||
|
||||
void Renderer::beginFrame() {
|
||||
assert(currentImage == UINT32_MAX);
|
||||
|
||||
|
@ -436,10 +376,6 @@ void Renderer::endPass() {
|
|||
}
|
||||
|
||||
void Renderer::swapBuffer(Window&) {
|
||||
/*TracyGpuZone("Swap");
|
||||
glfwSwapBuffers(ptr);
|
||||
TracyGpuCollect;*/
|
||||
|
||||
if(!swapChain->presentImage(currentImage, presentQueue, renderFinishedSemaphores[currentFrame]) || framebufferResized) {
|
||||
framebufferResized = false;
|
||||
recreateSwapChain();
|
||||
|
|
|
@ -45,6 +45,7 @@ private:
|
|||
VkDevice device;
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
std::optional<VkQueue> transferQueue;
|
||||
|
||||
std::unique_ptr<PhysicalDeviceInfo> physicalInfo;
|
||||
std::unique_ptr<SwapChain> swapChain;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "SwapChain.hpp"
|
||||
|
||||
#include "shared.hpp"
|
||||
#include "PhysicalDeviceInfo.hpp"
|
||||
|
||||
using namespace render::vk;
|
||||
|
||||
|
@ -26,8 +26,8 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
|
|||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
createInfo.surface = info.surface;
|
||||
createInfo.minImageCount = imageCount;
|
||||
createInfo.imageFormat = info.surfaceFormat.format;
|
||||
createInfo.imageColorSpace = info.surfaceFormat.colorSpace;
|
||||
createInfo.imageFormat = info.getFormat().format;
|
||||
createInfo.imageColorSpace = info.getFormat().colorSpace;
|
||||
createInfo.imageExtent = info.swapDetails.capabilities.currentExtent;
|
||||
createInfo.imageArrayLayers = 1;
|
||||
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
|
@ -66,7 +66,7 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
|
|||
createInfo.image = images[i];
|
||||
|
||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
createInfo.format = info.surfaceFormat.format;
|
||||
createInfo.format = info.getFormat().format;
|
||||
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <volk.h>
|
||||
|
||||
namespace buffer::vk {
|
||||
|
||||
struct VertexData {
|
||||
glm::vec2 pos;
|
||||
glm::vec3 color;
|
||||
|
||||
static VkVertexInputBindingDescription getBindingDescription() {
|
||||
VkVertexInputBindingDescription description{};
|
||||
description.binding = 0;
|
||||
description.stride = sizeof(VertexData);
|
||||
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
return description;
|
||||
}
|
||||
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
|
||||
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
|
||||
attributeDescriptions[0].binding = 0;
|
||||
attributeDescriptions[0].location = 0;
|
||||
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attributeDescriptions[0].offset = offsetof(VertexData, pos);
|
||||
attributeDescriptions[1].binding = 0;
|
||||
attributeDescriptions[1].location = 1;
|
||||
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
attributeDescriptions[1].offset = offsetof(VertexData, color);
|
||||
return attributeDescriptions;
|
||||
}
|
||||
};
|
||||
|
||||
const std::vector<VertexData> vertices = {
|
||||
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
|
||||
};
|
||||
const std::vector<uint16_t> indices = {
|
||||
0, 1, 2, 2, 3, 0
|
||||
};
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
using namespace world::client;
|
||||
|
||||
DistantUniverse::DistantUniverse(const connection& ct, const options& opt): Universe(), peer(ct),
|
||||
loadDistance(opt.loadDistance), keepDistance(opt.keepDistance) { }
|
||||
loadDistance(opt.loadDistance), keepDistance(opt.keepDistance), serverDistance(0) { }
|
||||
DistantUniverse::~DistantUniverse() { }
|
||||
|
||||
void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
||||
|
@ -46,11 +46,12 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
|||
ZoneScopedN("Missing");
|
||||
std::vector<chunk_pos> missing;
|
||||
//TODO: use easy sphere fill
|
||||
for (int x = -loadDistance; x <= loadDistance; x++) {
|
||||
for (int y = -loadDistance; y <= loadDistance; y++) {
|
||||
for (int z = -loadDistance; z <= loadDistance; z++) {
|
||||
const int queryDistance = std::min(loadDistance, serverDistance);
|
||||
for (int x = -queryDistance; x <= queryDistance; x++) {
|
||||
for (int y = -queryDistance; y <= queryDistance; y++) {
|
||||
for (int z = -queryDistance; z <= queryDistance; z++) {
|
||||
const auto dist2 = x * x + y * y + z * z;
|
||||
if (dist2 <= loadDistance * loadDistance) {
|
||||
if (dist2 <= queryDistance * queryDistance) {
|
||||
const auto p = diff + chunk_pos(x, y, z);
|
||||
if (chunks.inRange(p) && chunks.find(p) == chunks.end()) {
|
||||
missing.push_back(p);
|
||||
|
@ -58,7 +59,8 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
|||
}
|
||||
}}}
|
||||
if(!missing.empty()) {
|
||||
auto packet = net::Client::makePacket(net::client_packet_type::MISSING_CHUNKS, NULL, sizeof(area_id) + missing.size() * sizeof(chunk_pos), ENET_PACKET_FLAG_RELIABLE, peer.getSalt());
|
||||
auto packet = net::Client::makePacket(net::client_packet_type::MISSING_CHUNKS, NULL,
|
||||
sizeof(area_id) + missing.size() * sizeof(chunk_pos), ENET_PACKET_FLAG_RELIABLE, peer.getSalt());
|
||||
packet.write(area.first);
|
||||
packet.write(missing.data(), missing.size() * sizeof(chunk_pos));
|
||||
peer.send(packet.get(), net::channel_type::RELIABLE);
|
||||
|
@ -78,6 +80,11 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
|
|||
[&](packet_t* packet, channel_type){
|
||||
const server_packet_type type = static_cast<server_packet_type>(*packet->data);
|
||||
switch (type) {
|
||||
case server_packet_type::CAPABILITIES: {
|
||||
PacketReader(packet).read(serverDistance);
|
||||
break;
|
||||
}
|
||||
|
||||
case server_packet_type::COMPRESSION: {
|
||||
if(dict.has_value())
|
||||
break;
|
||||
|
|
|
@ -29,7 +29,8 @@ namespace world::client {
|
|||
|
||||
chunk_pos last_chunk = chunk_pos(INT_MAX);
|
||||
|
||||
int loadDistance;
|
||||
int keepDistance;
|
||||
ushort loadDistance;
|
||||
ushort keepDistance;
|
||||
ushort serverDistance;
|
||||
};
|
||||
}
|
|
@ -44,9 +44,9 @@ public:
|
|||
}
|
||||
|
||||
template<typename D, typename R>
|
||||
void pull(R onData, D onDisconnect, int delay = 0) {
|
||||
void pull(R onData, D onDisconnect, int delay = 0, int count = 10) {
|
||||
ENetEvent event;
|
||||
while(enet_host_service(host, &event, delay) > 0) {
|
||||
for(int i = 0; i < count && enet_host_service(host, &event, delay) > 0; i++) {
|
||||
switch(event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
LOG_D("Client reconnected");
|
||||
|
@ -110,6 +110,7 @@ public:
|
|||
}
|
||||
template<typename D>
|
||||
bool send(client_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
||||
static_assert(!std::is_pointer<D>::value);
|
||||
return send(type, &data, sizeof(data), channel, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ public:
|
|||
}
|
||||
|
||||
template<typename C, typename D, typename R>
|
||||
void pull(C onConnect, D onDisconnect, R onData, int delay = 0) {
|
||||
void pull(C onConnect, D onDisconnect, R onData, int delay = 10, int count = 10) {
|
||||
ENetEvent event;
|
||||
while(enet_host_service(host, &event, delay) > 0) {
|
||||
for(int i = 0; i < count && enet_host_service(host, &event, delay) > 0; i++) {
|
||||
switch(event.type) {
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
onConnect(event.peer, event.data);
|
||||
|
@ -72,6 +72,7 @@ public:
|
|||
}
|
||||
template<typename D>
|
||||
bool sendTo(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
||||
static_assert(!std::is_pointer<D>::value);
|
||||
return sendTo(peer, type, &data, sizeof(data), channel, flags);
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,7 @@ public:
|
|||
}
|
||||
template<typename D>
|
||||
bool send(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
||||
static_assert(!std::is_pointer<D>::value);
|
||||
return send(peer, type, &data, sizeof(data), channel, flags);
|
||||
}
|
||||
|
||||
|
@ -96,6 +98,7 @@ public:
|
|||
}
|
||||
template<typename D>
|
||||
void broadcast(server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
||||
static_assert(!std::is_pointer<D>::value);
|
||||
broadcast(type, &data, sizeof(data), channel, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,16 @@ enum class server_packet_type: enet_uint8 {
|
|||
/// {area_<chunk_pos>, zstd<chunk rle>} realable
|
||||
CHUNK = 17,
|
||||
/// Chunk changes
|
||||
/// {area_id, {chunk_pos, short(count), Chunk::Edit[]}[]} notify
|
||||
/// {area_id, {chunk_pos, ushort(count), Chunk::Edit[]}[]} notify
|
||||
/// FIXME: to big !!! MAYBE: compress
|
||||
EDITS = 18,
|
||||
|
||||
/// World compression dictionary
|
||||
/// zstd dict realable
|
||||
COMPRESSION = 24,
|
||||
/// Server capabilities
|
||||
/// ushort(loadDistance), MAYBE: more realable
|
||||
CAPABILITIES = 25,
|
||||
};
|
||||
enum class client_packet_type: enet_uint8 {
|
||||
/// Interact with voxels
|
||||
|
|
|
@ -15,9 +15,9 @@ namespace world {
|
|||
/// Distance management
|
||||
struct options {
|
||||
/// Radius in chunks to load if missing
|
||||
int loadDistance = 5;
|
||||
ushort loadDistance = 5;
|
||||
/// Radius in chunks to keep in memory
|
||||
int keepDistance = 6;
|
||||
ushort keepDistance = 6;
|
||||
};
|
||||
|
||||
/// Universe voxel ray intersection
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
#include "world/SharedUniverse.hpp"
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <chrono>
|
||||
|
||||
Server::Server(config::server::options& options): options(options) {
|
||||
//MAYBE: if allow local
|
||||
localHandle = options.allowLocal ? new server_handle() : nullptr;
|
||||
}
|
||||
Server::Server(config::server::options& options): options(options), localHandle(options.allowLocal ? new server_handle() : nullptr) { }
|
||||
Server::~Server() { }
|
||||
|
||||
const auto TPS = 10;
|
||||
|
@ -29,9 +27,16 @@ void Server::run() {
|
|||
signal(SIGINT, handle_signal);
|
||||
signal(SIGTERM, handle_signal);
|
||||
|
||||
auto lastTick = std::chrono::steady_clock::now();
|
||||
while(running && (localHandle == nullptr || localHandle->running)) {
|
||||
universe->update(1. / TPS); //FIXME: use chrono
|
||||
FrameMarkNamed("Server");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / TPS));
|
||||
FrameMarkStart("Server");
|
||||
auto startTick = std::chrono::steady_clock::now();
|
||||
const std::chrono::duration<float, std::ratio<1>> deltaTime = startTick - lastTick;
|
||||
universe->update(deltaTime.count());
|
||||
FrameMarkEnd("Server");
|
||||
while (std::chrono::steady_clock::now() < startTick + std::chrono::milliseconds(1000 / TPS)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
lastTick = startTick;
|
||||
}
|
||||
}
|
|
@ -328,9 +328,11 @@ struct net_client {
|
|||
};
|
||||
|
||||
void Universe::pullNetwork() {
|
||||
ZoneScopedN("Network");
|
||||
using namespace net;
|
||||
host.pull(
|
||||
[&](peer_t *peer, salt_t salt) {
|
||||
ZoneScopedN("Connect");
|
||||
LOG_D("Client connect from " << peer->address);
|
||||
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{ }));
|
||||
peer->data = client;
|
||||
|
@ -339,15 +341,18 @@ void Universe::pullNetwork() {
|
|||
host.sendTo<salt_t>(peer, server_packet_type::CHALLENGE, rnd, channel_type::RELIABLE);
|
||||
client->salt = salt ^ rnd;
|
||||
|
||||
host.send(peer, server_packet_type::CAPABILITIES, loadDistance, channel_type::RELIABLE);
|
||||
host.send(peer, server_packet_type::COMPRESSION, dict_content.data(), dict_content.size(), channel_type::RELIABLE);
|
||||
broadcastAreas();
|
||||
},
|
||||
[](peer_t *peer, disconnect_reason reason) {
|
||||
ZoneScopedN("Disconnect");
|
||||
LOG_D("Client disconnect from " << peer->address << " with " << (enet_uint32)reason);
|
||||
if (const auto data = Server::GetPeerData<net_client>(peer); data != nullptr)
|
||||
delete data;
|
||||
},
|
||||
[&](peer_t *peer, packet_t* packet, channel_type) {
|
||||
ZoneScopedN("Data");
|
||||
if(packet->dataLength < sizeof(client_packet_type) + sizeof(salt_t)) {
|
||||
LOG_D("Empty packet from " << peer->address);
|
||||
return;
|
||||
|
@ -403,7 +408,7 @@ void Universe::pullNetwork() {
|
|||
LOG_D("Bad packet from " << peer->address);
|
||||
break;
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
void Universe::broadcastAreas() {
|
||||
constexpr size_t ITEM_SIZE = sizeof(area_id) + sizeof(world::Area::params);
|
||||
|
@ -453,6 +458,7 @@ std::optional<world::Item> Universe::set(const area_<voxel_pos>& pos, const Voxe
|
|||
return {};
|
||||
}
|
||||
world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
||||
ZoneScopedN("Fill");
|
||||
ItemList list;
|
||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
|
||||
|
@ -476,6 +482,7 @@ world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val,
|
|||
}
|
||||
}
|
||||
}}}
|
||||
ZoneScopedN("Packet");
|
||||
size_t size = sizeof(area_id);
|
||||
for(const auto& part: edits) {
|
||||
size += sizeof(chunk_pos);
|
||||
|
|
|
@ -98,8 +98,8 @@ namespace world::server {
|
|||
using save_task_t = std::pair<area_it_t, robin_hood::pair<chunk_pos, std::shared_ptr<world::server::Chunk>>>;
|
||||
data::safe_queue<save_task_t> saveQueue; //NOTE: consider Area and Chunk const
|
||||
|
||||
int loadDistance;
|
||||
int keepDistance;
|
||||
ushort loadDistance;
|
||||
ushort keepDistance;
|
||||
std::string folderPath;
|
||||
|
||||
net::Server host;
|
||||
|
|
Loading…
Reference in New Issue