Vulkan basic buffer allocator
This commit is contained in:
parent
41eb636826
commit
c00f3f64a6
|
@ -19,9 +19,10 @@
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
class VkCtxScope {};
|
class VkCtxScope {};
|
||||||
|
class VkCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
using TracyVkCtx = void*;
|
using TracyVkCtx = tracy::VkCtx*;
|
||||||
|
|
||||||
#else
|
#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
|
#version 450 core
|
||||||
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
layout (constant_id = 0) const bool FOG = true;
|
layout (constant_id = 0) const bool FOG = true;
|
||||||
layout (constant_id = 1) const bool PBR = true;
|
layout (constant_id = 1) const bool PBR = true;
|
||||||
layout (constant_id = 2) const bool TRIPLANAR = false;
|
layout (constant_id = 2) const bool TRIPLANAR = false;
|
||||||
layout (constant_id = 3) const bool STOCHASTIC = false;
|
layout (constant_id = 3) const bool STOCHASTIC = false;
|
||||||
layout (constant_id = 4) const bool BLEND = true;
|
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(push_constant) uniform PushConstants {
|
||||||
layout(location = 0) out vec3 color;
|
mat4 Proj;
|
||||||
|
mat4 View;
|
||||||
|
#ifndef INSTANCED
|
||||||
|
mat4 Model;
|
||||||
|
#endif
|
||||||
|
|
||||||
uniform sampler2DArray TextureAtlas;
|
vec4 SphereProj;
|
||||||
uniform sampler2DArray NormalAtlas;
|
float Curvature;
|
||||||
uniform sampler2DArray HOSAtlas;
|
|
||||||
|
|
||||||
uniform mat4 View;
|
//MAYBE: extract
|
||||||
uniform vec3 FogColor;
|
vec3 FogColor;
|
||||||
|
float FogDepth;
|
||||||
|
|
||||||
|
vec3 LightInvDirection_worldspace;
|
||||||
|
} Push;
|
||||||
|
|
||||||
#ifdef GEOMETRY
|
#ifdef GEOMETRY
|
||||||
in GeometryData
|
layout (location = 0) in GeometryData
|
||||||
#else
|
#else
|
||||||
in VertexData
|
layout (location = 0) in VertexData
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
vec3 Position_modelspace;
|
vec3 Position_modelspace;
|
||||||
|
@ -40,6 +52,8 @@ in VertexData
|
||||||
float Depth;
|
float Depth;
|
||||||
} vs;
|
} vs;
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 color;
|
||||||
|
|
||||||
vec3 expand(vec3 v) {
|
vec3 expand(vec3 v) {
|
||||||
return (v - 0.5) * 2;
|
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);
|
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) {
|
if(STOCHASTIC) {
|
||||||
// triangular by approx 2*sqrt(3)
|
// triangular by approx 2*sqrt(3)
|
||||||
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
|
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 dx = dFdx(UV.xy);
|
||||||
vec2 dy = dFdy(UV.xy);
|
vec2 dy = dFdy(UV.xy);
|
||||||
|
|
||||||
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
|
return textureGrad(smpl, 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(smpl, 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;
|
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
|
||||||
} else {
|
} else {
|
||||||
return texture(sample, UV);
|
return texture(smpl, UV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 getTexture(sampler2DArray sample, vec2 UV) {
|
vec4 getTexture(sampler2DArray smpl, vec2 UV) {
|
||||||
#ifdef GEOMETRY
|
#ifdef GEOMETRY
|
||||||
if(BLEND) {
|
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]) {
|
if(vs.Textures[1] == vs.Textures[0]) {
|
||||||
return vs.Textures[2] == vs.Textures[0] ? colx :
|
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 {
|
} 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) : (
|
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) :
|
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 {
|
} else {
|
||||||
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
|
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
|
||||||
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
|
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
|
||||||
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 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
|
#else
|
||||||
return textureStochastic(sample, vec3(UV, vs.Texture));
|
return textureStochastic(smpl, vec3(UV, vs.Texture));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
vec3 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
|
||||||
return getTexture(sample, crdx).rgb * weights.x +
|
return getTexture(smpl, crdx).rgb * weights.x +
|
||||||
getTexture(sample, crdy).rgb * weights.y +
|
getTexture(smpl, crdy).rgb * weights.y +
|
||||||
getTexture(sample, crdz).rgb * weights.z;
|
getTexture(smpl, crdz).rgb * weights.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float texScale = 1. / UNIT_SIZE;
|
float texScale = 1. / UNIT_SIZE;
|
||||||
|
vec3 tex, texN, worldNormal, texHOS;
|
||||||
|
|
||||||
if(TRIPLANAR) {
|
if(TRIPLANAR) {
|
||||||
// Triplanar
|
// Triplanar
|
||||||
float plateauSize = 0.001;
|
float plateauSize = 0.001;
|
||||||
|
@ -173,7 +189,7 @@ if(PBR) {
|
||||||
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
|
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
|
||||||
vec3 TextureSpecularColor = vec3(.8) * texHOS.z;
|
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
|
// Light emission properties
|
||||||
// You probably want to put them as uniforms
|
// You probably want to put them as uniforms
|
||||||
|
@ -218,7 +234,7 @@ if(PBR) {
|
||||||
}
|
}
|
||||||
if(FOG) {
|
if(FOG) {
|
||||||
float ratio = exp(vs.Depth * 0.69)-1;
|
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));
|
color = pow(color, vec3(1.0 / 2.2));
|
||||||
if(color.r > 1 || color.g > 1 || color.b > 1) {
|
if(color.r > 1 || color.g > 1 || color.b > 1) {
|
|
@ -1,4 +1,5 @@
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
layout (constant_id = 0) const bool FOG = true;
|
layout (constant_id = 0) const bool FOG = true;
|
||||||
layout (constant_id = 1) const bool PBR = 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 (triangles) in;
|
||||||
layout (triangle_strip, max_vertices = 3) out;
|
layout (triangle_strip, max_vertices = 3) out;
|
||||||
|
|
||||||
in VertexData {
|
layout (location = 0) in VertexData {
|
||||||
vec3 Position_modelspace;
|
vec3 Position_modelspace;
|
||||||
flat uint Texture;
|
flat uint Texture;
|
||||||
vec3 FaceNormal_modelspace;
|
vec3 FaceNormal_modelspace;
|
||||||
|
@ -18,7 +19,7 @@ in VertexData {
|
||||||
float Depth;
|
float Depth;
|
||||||
} vs_in[];
|
} vs_in[];
|
||||||
|
|
||||||
out GeometryData {
|
layout (location = 0) out GeometryData {
|
||||||
vec3 Position_modelspace;
|
vec3 Position_modelspace;
|
||||||
flat uint Textures[3];
|
flat uint Textures[3];
|
||||||
vec3 TextureRatio;
|
vec3 TextureRatio;
|
|
@ -1,4 +1,5 @@
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
layout (constant_id = 0) const bool FOG = true;
|
layout (constant_id = 0) const bool FOG = true;
|
||||||
layout (constant_id = 1) const bool PBR = 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 = 5) const bool DO_CURVATURE = false;
|
||||||
layout (constant_id = 6) const bool CURV_DEPTH = true;
|
layout (constant_id = 6) const bool CURV_DEPTH = true;
|
||||||
|
|
||||||
layout(location = 0) in vec3 Position_modelspace;
|
layout(push_constant) uniform PushConstants {
|
||||||
layout(location = 1) in uint Texture_model;
|
mat4 Proj;
|
||||||
layout(location = 2) in vec3 Normal_modelspace;
|
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;
|
vec3 Position_modelspace;
|
||||||
flat uint Texture;
|
flat uint Texture;
|
||||||
vec3 FaceNormal_modelspace;
|
vec3 FaceNormal_modelspace;
|
||||||
|
@ -22,47 +44,35 @@ out VertexData {
|
||||||
float Depth;
|
float Depth;
|
||||||
} vs;
|
} 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(){
|
void main(){
|
||||||
|
#ifndef INSTANCED
|
||||||
|
mat4 Model = Push.Model;
|
||||||
|
#endif
|
||||||
|
|
||||||
vs.Position_modelspace = Position_modelspace;
|
vs.Position_modelspace = Position_modelspace;
|
||||||
|
|
||||||
if(DO_CURVATURE) {
|
if(DO_CURVATURE) {
|
||||||
if(Curvature > 0) {
|
if(Push.Curvature > 0) {
|
||||||
vec3 Position_areaspace = Position_modelspace + SphereProj.xyz;
|
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));
|
vec2 sph = vec2(acos(Position_areaspace.z / length(Position_areaspace.xyz)), atan(Position_areaspace.y, Position_areaspace.x));
|
||||||
if(CURV_DEPTH) {
|
float radius = CURV_DEPTH ?
|
||||||
float radius = max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z));
|
max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z)) :
|
||||||
} else {
|
Push.SphereProj.w;
|
||||||
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 - Push.SphereProj.xyz, Push.Curvature);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 Position_cameraspace = View * Model * vec4(vs.Position_modelspace, 1);
|
vec4 Position_cameraspace = Push.View * Model * vec4(vs.Position_modelspace, 1);
|
||||||
gl_Position = Proj * Position_cameraspace;
|
gl_Position = Push.Proj * Position_cameraspace;
|
||||||
|
|
||||||
if(FOG) {
|
if(FOG) {
|
||||||
vs.Depth = length(Position_cameraspace.xyz) / FogDepth;
|
vs.Depth = length(Position_cameraspace.xyz) / Push.FogDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
vs.Texture = Texture_model;
|
vs.Texture = Texture_model;
|
||||||
|
|
||||||
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
|
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
|
||||||
if(PBR)
|
if(PBR) {
|
||||||
// TODO: correct normal curvature
|
// TODO: correct normal curvature
|
||||||
vs.FaceNormal_worldspace = normalize((Model * vec4(vs.FaceNormal_modelspace, 0)).xyz);
|
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;
|
vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz;
|
||||||
|
|
||||||
// Vector that goes from the vertex to the light, in camera space
|
// 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")
|
BASEDIR=$(dirname "$0")
|
||||||
TARGETDIR="$BASEDIR/../content/shaders"
|
TARGETDIR="$BASEDIR/../content/shaders"
|
||||||
|
GLSL="glslc"
|
||||||
|
|
||||||
|
rm $TARGETDIR/*.spv
|
||||||
|
|
||||||
# Tris
|
# Tris
|
||||||
glslc -fshader-stage=vertex $BASEDIR/Tris.vs -o $TARGETDIR/Tris.vs.spv
|
$GLSL $BASEDIR/Tris.vert -o $TARGETDIR/Tris.vs.spv
|
||||||
glslc -fshader-stage=fragment $BASEDIR/Tris.fs -o $TARGETDIR/Tris.fs.spv
|
$GLSL $BASEDIR/Tris.frag -o $TARGETDIR/Tris.fs.spv
|
||||||
|
$GLSL $BASEDIR/Tris.vert $BASEDIR/Tris.frag -o $TARGETDIR/Tris.spv
|
||||||
|
|
||||||
# Color
|
# Color
|
||||||
glslc -fshader-stage=vertex $TARGETDIR/Color.vs -o $TARGETDIR/Color.vs.spv
|
$GLSL $BASEDIR/Color.vert -o $TARGETDIR/Color.vs.spv
|
||||||
glslc -fshader-stage=fragment $TARGETDIR/Color.fs -o $TARGETDIR/Color.fs.spv
|
$GLSL $BASEDIR/Color.frag -o $TARGETDIR/Color.fs.spv
|
||||||
|
|
||||||
# Sky
|
# Sky
|
||||||
glslc -fshader-stage=vertex $TARGETDIR/Sky.vs -o $TARGETDIR/Sky.vs.spv
|
$GLSL $BASEDIR/Sky.vert -o $TARGETDIR/Sky.vs.spv
|
||||||
glslc -fshader-stage=fragment $TARGETDIR/Sky.fs -o $TARGETDIR/Sky.fs.spv
|
$GLSL $BASEDIR/Sky.frag -o $TARGETDIR/Sky.fs.spv
|
||||||
|
|
||||||
# Voxel
|
# Voxel
|
||||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -o $TARGETDIR/Voxel.vs.spv
|
$GLSL $BASEDIR/Voxel.vert -o $TARGETDIR/Voxel.vs.spv
|
||||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -o $TARGETDIR/Voxel.fs.spv
|
$GLSL $BASEDIR/Voxel.frag -o $TARGETDIR/Voxel.fs.spv
|
||||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
|
$GLSL $BASEDIR/Voxel.vert -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
|
||||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DINSTANCED -o $TARGETDIR/Voxel.fs.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
|
$GLSL $BASEDIR/Voxel.vert -DGEOMETRY -o $TARGETDIR/Voxel.vs.geo.spv
|
||||||
glslc -fshader-stage=geometry $BASEDIR/Voxel.gs -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
|
$GLSL $BASEDIR/Voxel.geom -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
|
||||||
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
|
$GLSL $BASEDIR/Voxel.frag -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
|
||||||
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.vs.geo.ins.spv
|
$GLSL $BASEDIR/Voxel.vert -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
|
$GLSL $BASEDIR/Voxel.geom -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.frag -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.fs.geo.ins.spv
|
|
@ -35,6 +35,7 @@ void Client::run(server_handle* const localHandle) {
|
||||||
//TODO: loop
|
//TODO: loop
|
||||||
do {
|
do {
|
||||||
window.startFrame();
|
window.startFrame();
|
||||||
|
FrameMark;
|
||||||
{ // Update
|
{ // Update
|
||||||
ZoneScopedN("Update");
|
ZoneScopedN("Update");
|
||||||
static double lastTime = window.getTime();
|
static double lastTime = window.getTime();
|
||||||
|
@ -178,7 +179,6 @@ void Client::run(server_handle* const localHandle) {
|
||||||
ZoneScopedN("Swap");
|
ZoneScopedN("Swap");
|
||||||
pipeline->swapBuffer(window);
|
pipeline->swapBuffer(window);
|
||||||
inputs.poll();
|
inputs.poll();
|
||||||
FrameMarkNamed("Client");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.waitTargetFPS();
|
window.waitTargetFPS();
|
||||||
|
|
|
@ -183,8 +183,16 @@ namespace contouring {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatDualMC::onGui() {
|
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::Checkbox("Transparency", &transparency);
|
||||||
ImGui::SliderFloat("Iso", &iso, 0, 1);
|
ImGui::SliderFloat("Iso", &iso, 0, 1);
|
||||||
ImGui::Checkbox("Manifold", &manifold);
|
ImGui::Checkbox("Manifold", &manifold);
|
||||||
|
|
|
@ -49,8 +49,8 @@ namespace contouring {
|
||||||
|
|
||||||
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
|
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
|
||||||
|
|
||||||
int loadDistance = 3;
|
ushort loadDistance = 3;
|
||||||
int keepDistance = 4;
|
ushort keepDistance = 4;
|
||||||
bool transparency = false;
|
bool transparency = false;
|
||||||
float iso = .1f;
|
float iso = .1f;
|
||||||
bool manifold = true;
|
bool manifold = true;
|
||||||
|
|
|
@ -114,8 +114,12 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
|
||||||
|
|
||||||
if (options.debugMenu.world) {
|
if (options.debugMenu.world) {
|
||||||
ImGui::Begin("Debug: World", &options.debugMenu.world, ImGuiWindowFlags_AlwaysAutoResize);
|
ImGui::Begin("Debug: World", &options.debugMenu.world, ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
|
int load = options.world.loadDistance;
|
||||||
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
|
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;
|
actions |= Actions::World;
|
||||||
}
|
}
|
||||||
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {
|
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
#include "Allocator.hpp"
|
||||||
|
|
||||||
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
|
#include <TracyVulkan.hpp>
|
||||||
|
#include "buffer/VertexData.hpp"
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
using namespace render::vk;
|
||||||
|
|
||||||
|
const auto NO_DELETER = Allocator::MemoryDeleter(nullptr);
|
||||||
|
Allocator::memory_ptr get_null_ptr() { return Allocator::memory_ptr(nullptr, NO_DELETER); }
|
||||||
|
|
||||||
|
Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info) : device(device), indexedBufferMemory(get_null_ptr()) {
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(info.device, &properties);
|
||||||
|
|
||||||
|
{
|
||||||
|
if (!info.queueIndices.transferFamily.has_value()) {
|
||||||
|
LOG_W("No transfer queue family. Using graphics one");
|
||||||
|
}
|
||||||
|
const auto family = info.queueIndices.transferFamily.value_or(info.queueIndices.graphicsFamily.value());
|
||||||
|
|
||||||
|
vkGetDeviceQueue(device, family, 0, &transferQueue);
|
||||||
|
VkCommandPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
poolInfo.queueFamilyIndex = family;
|
||||||
|
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &transferPool) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create transfer pool!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandPool = transferPool;
|
||||||
|
allocInfo.commandBufferCount = 1;
|
||||||
|
|
||||||
|
vkAllocateCommandBuffers(device, &allocInfo, &transferBuffer);
|
||||||
|
tracyCtx = TracyVkContext(info.device, device, transferQueue, transferBuffer);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t vertexSize = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size();
|
||||||
|
size_t indexSize = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size();
|
||||||
|
size_t stagingSize = std::max(vertexSize, indexSize);
|
||||||
|
buffer_info stagingBuffer;
|
||||||
|
if(auto stagingMemory = createBuffer(stagingSize, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, stagingBuffer)) {
|
||||||
|
std::vector<buffer_requirement> requirements = {
|
||||||
|
{indexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT},
|
||||||
|
{vertexSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT}
|
||||||
|
};
|
||||||
|
if(std::vector<buffer_info> out; indexedBufferMemory = createBuffers(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, out)) {
|
||||||
|
indexBuffer = out[0];
|
||||||
|
vertexBuffer = out[1];
|
||||||
|
} else {
|
||||||
|
FATAL("Cannot allocate buffer memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
stagingMemory->write(buffer::vk::vertices.data(), vertexSize);
|
||||||
|
copyBuffer(stagingBuffer, vertexBuffer, vertexSize);
|
||||||
|
stagingMemory->write(buffer::vk::indices.data(), indexSize);
|
||||||
|
copyBuffer(stagingBuffer, indexBuffer, indexSize);
|
||||||
|
|
||||||
|
vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer
|
||||||
|
} else {
|
||||||
|
FATAL("Cannot allocate staging memory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Allocator::~Allocator() {
|
||||||
|
vkDestroyBuffer(device, indexBuffer.buffer, ALLOC);
|
||||||
|
vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC);
|
||||||
|
indexedBufferMemory.reset();
|
||||||
|
|
||||||
|
TracyVkDestroy(tracyCtx);
|
||||||
|
vkFreeCommandBuffers(device, transferPool, 1, &transferBuffer);
|
||||||
|
|
||||||
|
vkDestroyCommandPool(device, transferPool, ALLOC);
|
||||||
|
//NOTE: all allocations are delete by ~vector
|
||||||
|
}
|
||||||
|
|
||||||
|
void Allocator::setTracyZone(const char* name) {
|
||||||
|
TracyVkCollect(tracyCtx, transferBuffer);
|
||||||
|
TracyVkZone(tracyCtx, transferBuffer, name);
|
||||||
|
(void)name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator::memory_ptr Allocator::createBuffer(VkDeviceSize size, VkMemoryPropertyFlags properties, VkBufferUsageFlags usage, buffer_info& out) {
|
||||||
|
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, &out.buffer) != VK_SUCCESS) {
|
||||||
|
LOG_E("Failed to create buffer");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, out.buffer, &memRequirements);
|
||||||
|
|
||||||
|
if (auto memory = allocate(memRequirements, properties)) {
|
||||||
|
if(vkBindBufferMemory(device, out.buffer, memory->ref, memory->offset) == VK_SUCCESS)
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
LOG_E("Failed to allocate buffer memory");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
Allocator::memory_ptr Allocator::createBuffers(const std::vector<buffer_requirement>& requirements, VkMemoryPropertyFlags properties, std::vector<buffer_info>& out) {
|
||||||
|
assert(!requirements.empty());
|
||||||
|
out.resize(requirements.size());
|
||||||
|
|
||||||
|
// Create buffers
|
||||||
|
VkMemoryRequirements memRequirements = {0, 0, UINT32_MAX};
|
||||||
|
std::vector<std::pair<VkDeviceSize, VkDeviceSize>> ranges;
|
||||||
|
ranges.resize(requirements.size());
|
||||||
|
for (size_t i = 0; i < requirements.size(); i++) {
|
||||||
|
VkBufferCreateInfo bufferInfo{};
|
||||||
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bufferInfo.size = requirements[i].size;
|
||||||
|
bufferInfo.usage = requirements[i].usage;
|
||||||
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
if (vkCreateBuffer(device, &bufferInfo, ALLOC, &out[i].buffer) != VK_SUCCESS) {
|
||||||
|
LOG_E("Failed to create buffer");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryRequirements individualMemRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(device, out[i].buffer, &individualMemRequirements);
|
||||||
|
memRequirements.alignment = std::max(memRequirements.alignment, individualMemRequirements.alignment);
|
||||||
|
memRequirements.memoryTypeBits &= individualMemRequirements.memoryTypeBits;
|
||||||
|
ranges[i].first = individualMemRequirements.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align blocks
|
||||||
|
auto aligned = [&](VkDeviceSize offset) {
|
||||||
|
if (offset % memRequirements.alignment == 0)
|
||||||
|
return offset;
|
||||||
|
return offset + memRequirements.alignment - (offset % memRequirements.alignment);
|
||||||
|
};
|
||||||
|
ranges[0].second = 0;
|
||||||
|
for (size_t i = 1; i < requirements.size(); i++) {
|
||||||
|
ranges[i].second = aligned(ranges[i-1].second + ranges[i-1].first);
|
||||||
|
}
|
||||||
|
memRequirements.size = aligned(ranges.back().second + ranges.back().first);
|
||||||
|
|
||||||
|
// Bind memory
|
||||||
|
if (auto memory = allocate(memRequirements, properties)) {
|
||||||
|
for (size_t i = 0; i < requirements.size(); i++) {
|
||||||
|
if (vkBindBufferMemory(device, out[i].buffer, memory->ref, memory->offset + ranges[i].second) != VK_SUCCESS) {
|
||||||
|
LOG_E("Failed to bind buffer");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
LOG_E("Failed to allocate buffers");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkMemoryPropertyFlags properties) {
|
||||||
|
//TODO: search for existing allocation
|
||||||
|
//TODO: allocate more ???
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
allocInfo.allocationSize = requirements.size;
|
||||||
|
if (const auto memIdx = findMemory(requirements.memoryTypeBits, properties, requirements.size)) {
|
||||||
|
//TODO: check budget
|
||||||
|
allocInfo.memoryTypeIndex = memIdx.value();
|
||||||
|
} else {
|
||||||
|
LOG_E("No suitable memory heap");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
if (vkAllocateMemory(device, &allocInfo, ALLOC, &memory) != VK_SUCCESS) {
|
||||||
|
LOG_E("Failed to allocate memory!");
|
||||||
|
return get_null_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ptr = nullptr;
|
||||||
|
if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
|
||||||
|
vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, &ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto allocation = allocations.emplace_back(new Allocation(device, memory, allocInfo.allocationSize, allocInfo.memoryTypeIndex, ptr)).get();
|
||||||
|
allocation->areas.push_back({allocInfo.allocationSize, 0});
|
||||||
|
|
||||||
|
return memory_ptr(new memory_area{memory, requirements.size, 0, ptr}, allocation->deleter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Allocator::copyBuffer(buffer_info src, buffer_info dst, VkDeviceSize size) {
|
||||||
|
//FIXME: assert no out of range
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
|
||||||
|
vkBeginCommandBuffer(transferBuffer, &beginInfo);
|
||||||
|
|
||||||
|
VkBufferCopy copyRegion{};
|
||||||
|
copyRegion.srcOffset = 0;
|
||||||
|
copyRegion.dstOffset = 0;
|
||||||
|
copyRegion.size = size;
|
||||||
|
vkCmdCopyBuffer(transferBuffer, src.buffer, dst.buffer, 1, ©Region);
|
||||||
|
|
||||||
|
vkEndCommandBuffer(transferBuffer);
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo{};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &transferBuffer;
|
||||||
|
|
||||||
|
vkQueueSubmit(transferQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(transferQueue); //MAYBE: use fences
|
||||||
|
vkResetCommandBuffer(transferBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint32_t> Allocator::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags requirement, VkDeviceSize size) const {
|
||||||
|
#if DEBUG
|
||||||
|
LOG_D("available memory:");
|
||||||
|
for (uint32_t i = 0; i < properties.memoryTypeCount; i++) {
|
||||||
|
LOG_D('\t' << i << ": " << ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ? "local " : "")
|
||||||
|
<< ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ? "visible " : "")
|
||||||
|
<< ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) ? "coherent " : "")
|
||||||
|
<< ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) ? "cached " : "")
|
||||||
|
<< ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) ? "lazy " : "")
|
||||||
|
<< ((properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) ? "protected " : "")
|
||||||
|
<< properties.memoryHeaps[properties.memoryTypes[i].heapIndex].size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (uint32_t i = 0; i < properties.memoryTypeCount; i++) {
|
||||||
|
if ((typeFilter & (1 << i)) && (properties.memoryTypes[i].propertyFlags & requirement) == requirement) {
|
||||||
|
VkDeviceSize usage = size;
|
||||||
|
for(const auto& alloc: allocations) {
|
||||||
|
if(alloc->memoryType == i)
|
||||||
|
usage += alloc->size;
|
||||||
|
}
|
||||||
|
VkDeviceSize budget = properties.memoryHeaps[properties.memoryTypes[i].heapIndex].size;
|
||||||
|
//TODO: use memory budjet extension
|
||||||
|
if(budget >= usage) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Allocator::memory_area::write(const void* data, size_t data_size, size_t write_offset) {
|
||||||
|
assert(ptr != nullptr && size >= write_offset + data_size);
|
||||||
|
memcpy(ptr + write_offset, data, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Allocator::MemoryDeleter::operator()(memory_area* area) {
|
||||||
|
assert(area != nullptr && "Deleting null area");
|
||||||
|
if(owner != nullptr) {
|
||||||
|
for (auto it = owner->areas.begin(); it != owner->areas.end(); ++it) {
|
||||||
|
if(it->offset == area->offset) {
|
||||||
|
assert(it->size == area->size);
|
||||||
|
owner->areas.erase(it);
|
||||||
|
delete area;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_E("Allocation area not found");
|
||||||
|
delete area;
|
||||||
|
}
|
||||||
|
Allocator::Allocation::Allocation(VkDevice device, VkDeviceMemory memory, VkDeviceSize size, uint32_t memoryType, void *ptr):
|
||||||
|
device(device), memory(memory), size(size), memoryType(memoryType), ptr(ptr), deleter(this) { }
|
||||||
|
Allocator::Allocation::~Allocation() {
|
||||||
|
if(!areas.empty())
|
||||||
|
LOG_E("Freeing " << areas.size() << " floating buffers");
|
||||||
|
|
||||||
|
if(ptr != nullptr)
|
||||||
|
vkUnmapMemory(device, memory);
|
||||||
|
|
||||||
|
vkFreeMemory(device, memory, ALLOC);
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "forward.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace tracy {
|
||||||
|
class VkCtx;
|
||||||
|
}
|
||||||
|
typedef tracy::VkCtx* TracyVkCtx;
|
||||||
|
namespace render::vk {
|
||||||
|
|
||||||
|
class Allocator {
|
||||||
|
private:
|
||||||
|
struct Allocation;
|
||||||
|
public:
|
||||||
|
Allocator(VkDevice, const PhysicalDeviceInfo&);
|
||||||
|
~Allocator();
|
||||||
|
|
||||||
|
struct memory_area {
|
||||||
|
VkDeviceMemory ref;
|
||||||
|
VkDeviceSize size;
|
||||||
|
VkDeviceSize offset;
|
||||||
|
void *ptr = nullptr;
|
||||||
|
|
||||||
|
void write(const void*, VkDeviceSize size, VkDeviceSize offset = 0);
|
||||||
|
void read(void*, VkDeviceSize size, VkDeviceSize offset = 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class MemoryDeleter {
|
||||||
|
public:
|
||||||
|
MemoryDeleter(Allocation *owner): owner(owner) { }
|
||||||
|
void operator()(memory_area *);
|
||||||
|
private:
|
||||||
|
Allocation *owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
using memory_ptr = std::unique_ptr<memory_area, MemoryDeleter>;
|
||||||
|
|
||||||
|
memory_ptr allocate(VkMemoryRequirements, VkMemoryPropertyFlags);
|
||||||
|
bool deallocate(const memory_area&);
|
||||||
|
|
||||||
|
struct buffer_info {
|
||||||
|
VkBuffer buffer = nullptr;
|
||||||
|
};
|
||||||
|
memory_ptr createBuffer(VkDeviceSize, VkMemoryPropertyFlags, VkBufferUsageFlags, buffer_info&);
|
||||||
|
struct buffer_requirement {
|
||||||
|
VkDeviceSize size;
|
||||||
|
VkBufferUsageFlags usage;
|
||||||
|
};
|
||||||
|
memory_ptr createBuffers(const std::vector<buffer_requirement> &, VkMemoryPropertyFlags, std::vector<buffer_info> &);
|
||||||
|
//TODO: create Buffer{MemoryArea + VkBuffer}
|
||||||
|
//TODO: create readonly buffer with data
|
||||||
|
|
||||||
|
void copyBuffer(buffer_info srcBuffer, buffer_info dstBuffer, VkDeviceSize size);
|
||||||
|
|
||||||
|
std::pair<VkBuffer, VkBuffer> getBuffer() { return {vertexBuffer.buffer, indexBuffer.buffer}; }
|
||||||
|
void setTracyZone(const char* name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<uint32_t> findMemory(uint32_t, VkMemoryPropertyFlags, VkDeviceSize size = 0) const;
|
||||||
|
|
||||||
|
struct Allocation {
|
||||||
|
Allocation(VkDevice, VkDeviceMemory, VkDeviceSize, uint32_t, void *ptr);
|
||||||
|
~Allocation();
|
||||||
|
|
||||||
|
const VkDevice device;
|
||||||
|
const VkDeviceMemory memory;
|
||||||
|
const VkDeviceSize size;
|
||||||
|
const uint32_t memoryType;
|
||||||
|
const void *ptr = nullptr;
|
||||||
|
const MemoryDeleter deleter;
|
||||||
|
|
||||||
|
struct area { VkDeviceSize size; VkDeviceSize offset; };
|
||||||
|
std::vector<area> areas;
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDevice device;
|
||||||
|
VkPhysicalDeviceMemoryProperties properties;
|
||||||
|
|
||||||
|
VkQueue transferQueue;
|
||||||
|
VkCommandPool transferPool;
|
||||||
|
VkCommandBuffer transferBuffer; // MAYBE: parallel upload
|
||||||
|
TracyVkCtx tracyCtx;
|
||||||
|
|
||||||
|
buffer_info vertexBuffer;
|
||||||
|
buffer_info indexBuffer;
|
||||||
|
memory_ptr indexedBufferMemory;
|
||||||
|
std::vector<std::unique_ptr<Allocation>> allocations;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,31 +1,36 @@
|
||||||
#include "CommandPool.hpp"
|
#include "CommandCenter.hpp"
|
||||||
|
|
||||||
#include "shared.hpp"
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
#include "../Renderer.hpp"
|
#include "../Renderer.hpp"
|
||||||
|
#include "buffer/VertexData.hpp"
|
||||||
|
|
||||||
using namespace render::vk;
|
using namespace render::vk;
|
||||||
|
|
||||||
CommandPool::CommandPool(VkDevice device, const std::vector<VkImageView>& views, PipelineRef pipe, const PhysicalDeviceInfo& info, const renderOptions& opt):
|
CommandCenter::CommandCenter(VkDevice device, const std::vector<VkImageView> &views, PipelineRef pipe,
|
||||||
device(device) {
|
std::pair<VkBuffer, VkBuffer> buffer, const PhysicalDeviceInfo &info, const renderOptions &opt) : device(device) {
|
||||||
|
{
|
||||||
|
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
|
||||||
|
VkCommandPoolCreateInfo poolInfo{};
|
||||||
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
|
||||||
|
poolInfo.flags = 0;
|
||||||
|
|
||||||
VkCommandPoolCreateInfo poolInfo{};
|
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
FATAL("Failed to create graphics pool!");
|
||||||
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
|
}
|
||||||
poolInfo.flags = 0; // Optional
|
|
||||||
|
|
||||||
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
|
|
||||||
FATAL("Failed to create command pool!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allocate(views, pipe, info.swapDetails.capabilities.currentExtent, opt);
|
allocate(views, pipe, buffer, info.swapDetails.capabilities.currentExtent, opt);
|
||||||
}
|
}
|
||||||
CommandPool::~CommandPool() {
|
CommandCenter::~CommandCenter() {
|
||||||
if(!freed)
|
if(!freed)
|
||||||
free();
|
free();
|
||||||
|
|
||||||
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
||||||
}
|
}
|
||||||
void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, VkExtent2D extent, const renderOptions& opt) {
|
void CommandCenter::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, std::pair<VkBuffer, VkBuffer> buffer, VkExtent2D extent,
|
||||||
|
const renderOptions& opt)
|
||||||
|
{
|
||||||
assert(freed);
|
assert(freed);
|
||||||
|
|
||||||
framebuffers.resize(views.size());
|
framebuffers.resize(views.size());
|
||||||
|
@ -47,16 +52,17 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graphicsBuffers.resize(framebuffers.size());
|
{
|
||||||
|
graphicsBuffers.resize(framebuffers.size());
|
||||||
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.commandPool = graphicsPool;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandBufferCount = (uint32_t) graphicsBuffers.size();
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
if (vkAllocateCommandBuffers(device, &allocInfo, graphicsBuffers.data()) != VK_SUCCESS) {
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
FATAL("Failed to allocate graphics buffers!");
|
||||||
allocInfo.commandPool = graphicsPool;
|
}
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
||||||
allocInfo.commandBufferCount = (uint32_t) graphicsBuffers.size();
|
|
||||||
|
|
||||||
if (vkAllocateCommandBuffers(device, &allocInfo, graphicsBuffers.data()) != VK_SUCCESS) {
|
|
||||||
FATAL("Failed to allocate command buffers!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < graphicsBuffers.size(); i++) {
|
for (size_t i = 0; i < graphicsBuffers.size(); i++) {
|
||||||
|
@ -82,17 +88,21 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
|
||||||
|
|
||||||
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
|
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
|
||||||
vkCmdDraw(graphicsBuffers[i], 3, 1, 0, 0);
|
VkBuffer vertexBuffers[] = {buffer.first};
|
||||||
|
VkDeviceSize offsets[] = {0};
|
||||||
|
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdBindIndexBuffer(graphicsBuffers[i], buffer.second, 0, VK_INDEX_TYPE_UINT16);
|
||||||
|
vkCmdDrawIndexed(graphicsBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
|
||||||
vkCmdEndRenderPass(graphicsBuffers[i]);
|
vkCmdEndRenderPass(graphicsBuffers[i]);
|
||||||
|
|
||||||
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
|
||||||
FATAL("Failed to record command buffer!");
|
FATAL("Failed to record graphics buffer!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freed = false;
|
freed = false;
|
||||||
}
|
}
|
||||||
void CommandPool::free() {
|
void CommandCenter::free() {
|
||||||
assert(!freed);
|
assert(!freed);
|
||||||
for (size_t i = 0; i < framebuffers.size(); i++) {
|
for (size_t i = 0; i < framebuffers.size(); i++) {
|
||||||
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
|
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
|
||||||
|
@ -103,7 +113,7 @@ void CommandPool::free() {
|
||||||
freed = true;
|
freed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
||||||
assert(!freed);
|
assert(!freed);
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{};
|
VkSubmitInfo submitInfo{};
|
||||||
|
@ -126,4 +136,4 @@ void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphor
|
||||||
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, submittedFence) != VK_SUCCESS) {
|
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, submittedFence) != VK_SUCCESS) {
|
||||||
FATAL("Failed to submit draw command buffer!");
|
FATAL("Failed to submit draw command buffer!");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "forward.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace render::vk {
|
||||||
|
class SwapChain;
|
||||||
|
class Pipeline;
|
||||||
|
|
||||||
|
class CommandCenter {
|
||||||
|
public:
|
||||||
|
CommandCenter(VkDevice, const std::vector<VkImageView>&, PipelineRef, std::pair<VkBuffer, VkBuffer>, const PhysicalDeviceInfo&, const renderOptions&);
|
||||||
|
~CommandCenter();
|
||||||
|
|
||||||
|
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
||||||
|
|
||||||
|
void allocate(const std::vector<VkImageView> &, PipelineRef, std::pair<VkBuffer, VkBuffer>, VkExtent2D, const renderOptions&);
|
||||||
|
void free();
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkDevice device;
|
||||||
|
|
||||||
|
std::vector<VkFramebuffer> framebuffers;
|
||||||
|
|
||||||
|
VkQueue graphicsQueue;
|
||||||
|
VkCommandPool graphicsPool;
|
||||||
|
std::vector<VkCommandBuffer> graphicsBuffers;
|
||||||
|
|
||||||
|
bool freed = true;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "forward.hpp"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace render::vk {
|
|
||||||
class SwapChain;
|
|
||||||
class Pipeline;
|
|
||||||
|
|
||||||
class CommandPool {
|
|
||||||
public:
|
|
||||||
CommandPool(VkDevice, const std::vector<VkImageView>&, PipelineRef, const PhysicalDeviceInfo&, const renderOptions&);
|
|
||||||
~CommandPool();
|
|
||||||
|
|
||||||
void submitGraphics(uint32_t, VkQueue, VkSemaphore, VkSemaphore, VkFence);
|
|
||||||
|
|
||||||
void allocate(const std::vector<VkImageView>&, PipelineRef, VkExtent2D, const renderOptions&);
|
|
||||||
void free();
|
|
||||||
|
|
||||||
private:
|
|
||||||
VkDevice device;
|
|
||||||
|
|
||||||
std::vector<VkFramebuffer> framebuffers;
|
|
||||||
|
|
||||||
VkCommandPool graphicsPool;
|
|
||||||
std::vector<VkCommandBuffer> graphicsBuffers;
|
|
||||||
bool freed = true;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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());
|
||||||
|
|
||||||
|
uint32_t 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 " : "")
|
||||||
|
<< (presentSupport ? "present " : "")
|
||||||
|
<< (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];
|
||||||
|
}
|
|
@ -17,15 +17,23 @@ struct SwapChainSupportDetails {
|
||||||
struct QueueFamilyIndices {
|
struct QueueFamilyIndices {
|
||||||
std::optional<uint32_t> graphicsFamily;
|
std::optional<uint32_t> graphicsFamily;
|
||||||
std::optional<uint32_t> presentFamily;
|
std::optional<uint32_t> presentFamily;
|
||||||
|
std::optional<uint32_t> transferFamily;
|
||||||
static QueueFamilyIndices Query(VkPhysicalDevice, VkSurfaceKHR);
|
static QueueFamilyIndices Query(VkPhysicalDevice, VkSurfaceKHR);
|
||||||
bool isComplete() const { return graphicsFamily.has_value() && presentFamily.has_value(); }
|
bool isComplete() const { return graphicsFamily.has_value() && presentFamily.has_value(); }
|
||||||
|
bool isOptimal() const { return isComplete() && transferFamily.has_value(); }
|
||||||
};
|
};
|
||||||
struct PhysicalDeviceInfo {
|
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)) { }
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR getFormat() const;
|
||||||
|
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
|
VkPhysicalDevice device = VK_NULL_HANDLE;
|
||||||
|
VkSurfaceKHR surface;
|
||||||
SwapChainSupportDetails swapDetails;
|
SwapChainSupportDetails swapDetails;
|
||||||
QueueFamilyIndices queueIndices;
|
QueueFamilyIndices queueIndices;
|
||||||
VkSurfaceFormatKHR surfaceFormat;
|
|
||||||
VkSurfaceKHR surface;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
#include "Pipeline.hpp"
|
#include "Pipeline.hpp"
|
||||||
|
|
||||||
#include "shared.hpp"
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
#include "../../../core/data/file.hpp"
|
#include "../../../core/data/file.hpp"
|
||||||
#include "../Renderer.hpp"
|
#include "../Renderer.hpp"
|
||||||
|
#include "buffer/VertexData.hpp"
|
||||||
|
|
||||||
#define CONTENT_DIR "content/"
|
#define CONTENT_DIR "content/"
|
||||||
#define SHADER_DIR CONTENT_DIR "shaders/"
|
#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) {
|
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
|
||||||
{ // Render pass
|
{ // Render pass
|
||||||
VkAttachmentDescription colorAttachment{};
|
VkAttachmentDescription colorAttachment{};
|
||||||
colorAttachment.format = info.surfaceFormat.format;
|
colorAttachment.format = info.getFormat().format;
|
||||||
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
@ -110,10 +111,13 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
|
||||||
vertexInputInfo.pVertexBindingDescriptions = nullptr; // TODO: uniforms, and buffers
|
auto bindingDescription = buffer::vk::VertexData::getBindingDescription();
|
||||||
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||||
vertexInputInfo.pVertexAttributeDescriptions = nullptr; // TODO: uniforms, and buffers
|
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||||
|
auto attributeDescriptions = buffer::vk::VertexData::getAttributeDescriptions();
|
||||||
|
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
||||||
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
#include "UI.hpp"
|
#include "UI.hpp"
|
||||||
#include "../../Window.hpp"
|
#include "../../Window.hpp"
|
||||||
#include "shared.hpp"
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
|
#include "Allocator.hpp"
|
||||||
#include "SwapChain.hpp"
|
#include "SwapChain.hpp"
|
||||||
#include "Pipeline.hpp"
|
#include "Pipeline.hpp"
|
||||||
#include "CommandPool.hpp"
|
#include "CommandCenter.hpp"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -21,24 +22,12 @@ void set_current_extent(VkSurfaceCapabilitiesKHR &capabilities, GLFWwindow *ptr)
|
||||||
Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInfo& info, const renderOptions& opt):
|
Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInfo& info, const renderOptions& opt):
|
||||||
options(opt), instance(instance), surface(info.surface), device(device),
|
options(opt), instance(instance), surface(info.surface), device(device),
|
||||||
physicalInfo(std::make_unique<PhysicalDeviceInfo>(info)) {
|
physicalInfo(std::make_unique<PhysicalDeviceInfo>(info)) {
|
||||||
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
|
|
||||||
vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue);
|
|
||||||
|
|
||||||
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
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];
|
|
||||||
}();
|
|
||||||
|
|
||||||
|
allocator = std::make_unique<Allocator>(device, *physicalInfo.get());
|
||||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||||
commandPool = std::make_unique<CommandPool>(device, swapChain->getImageViews(), pipeline->getRef(), *physicalInfo.get(), options);
|
commandCenter = std::make_unique<CommandCenter>(device, swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), *physicalInfo.get(), options);
|
||||||
|
|
||||||
{
|
{
|
||||||
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
||||||
|
@ -73,7 +62,8 @@ Renderer::~Renderer() {
|
||||||
vkDestroySemaphore(device, imageAvailableSemaphores[i], ALLOC);
|
vkDestroySemaphore(device, imageAvailableSemaphores[i], ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
commandPool.reset();
|
commandCenter.reset();
|
||||||
|
allocator.reset();
|
||||||
|
|
||||||
vkDestroyDevice(device, ALLOC);
|
vkDestroyDevice(device, ALLOC);
|
||||||
vkDestroySurfaceKHR(instance, surface, ALLOC);
|
vkDestroySurfaceKHR(instance, surface, ALLOC);
|
||||||
|
@ -81,7 +71,6 @@ Renderer::~Renderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::recreateSwapChain() {
|
void Renderer::recreateSwapChain() {
|
||||||
LOG_D("Recreating swapchain");
|
|
||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
destroySwapChain();
|
destroySwapChain();
|
||||||
|
|
||||||
|
@ -89,10 +78,10 @@ void Renderer::recreateSwapChain() {
|
||||||
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
|
||||||
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
|
||||||
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
|
||||||
commandPool->allocate(swapChain->getImageViews(), pipeline->getRef(), physicalInfo->swapDetails.capabilities.currentExtent, options);
|
commandCenter->allocate(swapChain->getImageViews(), pipeline->getRef(), allocator->getBuffer(), physicalInfo->swapDetails.capabilities.currentExtent, options);
|
||||||
}
|
}
|
||||||
void Renderer::destroySwapChain() {
|
void Renderer::destroySwapChain() {
|
||||||
commandPool->free();
|
commandCenter->free();
|
||||||
pipeline.reset();
|
pipeline.reset();
|
||||||
swapChain.reset();
|
swapChain.reset();
|
||||||
}
|
}
|
||||||
|
@ -215,7 +204,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto version = volkGetInstanceVersion();
|
const auto version = volkGetInstanceVersion();
|
||||||
LOG_D("Vulkan " << VK_VERSION_MAJOR(version) << '.' << VK_VERSION_MINOR(version) << '.' << VK_VERSION_PATCH(version) << ", GLSL TODO:");
|
LOG_D("Vulkan " << VK_VERSION_MAJOR(version) << '.' << VK_VERSION_MINOR(version) << '.' << VK_VERSION_PATCH(version) << ", GLSL precompiled");
|
||||||
|
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
if (glfwCreateWindowSurface(instance, window.getPtr(), ALLOC, &surface) != VK_SUCCESS) {
|
if (glfwCreateWindowSurface(instance, window.getPtr(), ALLOC, &surface) != VK_SUCCESS) {
|
||||||
|
@ -266,12 +255,11 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
|
||||||
score += deviceProperties.limits.maxImageDimension2D;
|
score += deviceProperties.limits.maxImageDimension2D;
|
||||||
//TODO: check others limits
|
//TODO: check others limits
|
||||||
|
|
||||||
auto infos = PhysicalDeviceInfo{device, window.getPtr(),
|
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface);
|
||||||
SwapChainSupportDetails::Query(device, surface), QueueFamilyIndices::Query(device, surface),
|
|
||||||
VkSurfaceFormatKHR(), surface};
|
|
||||||
|
|
||||||
if (!infos.queueIndices.isComplete())
|
if (!infos.queueIndices.isComplete())
|
||||||
continue;
|
continue;
|
||||||
|
if (infos.queueIndices.isOptimal())
|
||||||
|
score += 5000;
|
||||||
|
|
||||||
if (!infos.swapDetails.isValid())
|
if (!infos.swapDetails.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
@ -339,63 +327,12 @@ void Renderer::loadUI(Window& w) {
|
||||||
UI::Load(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() {
|
void Renderer::beginFrame() {
|
||||||
assert(currentImage == UINT32_MAX);
|
assert(currentImage == UINT32_MAX);
|
||||||
|
|
||||||
//FIXME: TracyGpuZone("Render");
|
|
||||||
if (auto newImage = swapChain->acquireNextImage(imageAvailableSemaphores[currentFrame], inFlightFences[currentFrame])) {
|
if (auto newImage = swapChain->acquireNextImage(imageAvailableSemaphores[currentFrame], inFlightFences[currentFrame])) {
|
||||||
currentImage = newImage.value();
|
currentImage = newImage.value();
|
||||||
|
allocator->setTracyZone("Submit");
|
||||||
} else {
|
} else {
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
beginFrame();
|
beginFrame();
|
||||||
|
@ -405,7 +342,7 @@ void Renderer::beginFrame() {
|
||||||
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
||||||
assert(currentImage < swapChain->getImageViews().size());
|
assert(currentImage < swapChain->getImageViews().size());
|
||||||
|
|
||||||
commandPool->submitGraphics(currentImage, graphicsQueue, imageAvailableSemaphores[currentFrame],
|
commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame],
|
||||||
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
||||||
|
|
||||||
/*WorldPass->useIt();
|
/*WorldPass->useIt();
|
||||||
|
@ -436,11 +373,7 @@ void Renderer::endPass() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::swapBuffer(Window&) {
|
void Renderer::swapBuffer(Window&) {
|
||||||
/*TracyGpuZone("Swap");
|
if(!swapChain->presentImage(currentImage, renderFinishedSemaphores[currentFrame]) || framebufferResized) {
|
||||||
glfwSwapBuffers(ptr);
|
|
||||||
TracyGpuCollect;*/
|
|
||||||
|
|
||||||
if(!swapChain->presentImage(currentImage, presentQueue, renderFinishedSemaphores[currentFrame]) || framebufferResized) {
|
|
||||||
framebufferResized = false;
|
framebufferResized = false;
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
}
|
}
|
||||||
|
@ -448,6 +381,7 @@ void Renderer::swapBuffer(Window&) {
|
||||||
currentFrame = (currentFrame + 1) % renderFinishedSemaphores.size();
|
currentFrame = (currentFrame + 1) % renderFinishedSemaphores.size();
|
||||||
currentImage = UINT32_MAX;
|
currentImage = UINT32_MAX;
|
||||||
|
|
||||||
|
allocator->setTracyZone("Swap");
|
||||||
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
#include "forward.hpp"
|
#include "forward.hpp"
|
||||||
|
|
||||||
namespace render::vk {
|
namespace render::vk {
|
||||||
|
class Allocator;
|
||||||
class SwapChain;
|
class SwapChain;
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
class CommandPool;
|
class CommandCenter;
|
||||||
|
|
||||||
/// Vulkan rendering
|
/// Vulkan rendering
|
||||||
class Renderer final: public render::Renderer {
|
class Renderer final: public render::Renderer {
|
||||||
|
@ -43,13 +44,12 @@ private:
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkQueue graphicsQueue;
|
|
||||||
VkQueue presentQueue;
|
|
||||||
|
|
||||||
std::unique_ptr<PhysicalDeviceInfo> physicalInfo;
|
std::unique_ptr<PhysicalDeviceInfo> physicalInfo;
|
||||||
|
std::unique_ptr<Allocator> allocator;
|
||||||
std::unique_ptr<SwapChain> swapChain;
|
std::unique_ptr<SwapChain> swapChain;
|
||||||
std::unique_ptr<Pipeline> pipeline;
|
std::unique_ptr<Pipeline> pipeline;
|
||||||
std::unique_ptr<CommandPool> commandPool;
|
std::unique_ptr<CommandCenter> commandCenter;
|
||||||
|
|
||||||
size_t currentFrame = 0;
|
size_t currentFrame = 0;
|
||||||
uint32_t currentImage = UINT32_MAX;
|
uint32_t currentImage = UINT32_MAX;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#include "SwapChain.hpp"
|
#include "SwapChain.hpp"
|
||||||
|
|
||||||
#include "shared.hpp"
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
|
|
||||||
using namespace render::vk;
|
using namespace render::vk;
|
||||||
|
|
||||||
SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(device) {
|
SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(device) {
|
||||||
|
vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue);
|
||||||
{ // Swapchain
|
{ // Swapchain
|
||||||
VkPresentModeKHR presentMode = [&]() {
|
VkPresentModeKHR presentMode = [&]() {
|
||||||
// MAYBE: add prefer no triple buffering options
|
// MAYBE: add prefer no triple buffering options
|
||||||
|
@ -26,14 +27,14 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
createInfo.surface = info.surface;
|
createInfo.surface = info.surface;
|
||||||
createInfo.minImageCount = imageCount;
|
createInfo.minImageCount = imageCount;
|
||||||
createInfo.imageFormat = info.surfaceFormat.format;
|
createInfo.imageFormat = info.getFormat().format;
|
||||||
createInfo.imageColorSpace = info.surfaceFormat.colorSpace;
|
createInfo.imageColorSpace = info.getFormat().colorSpace;
|
||||||
createInfo.imageExtent = info.swapDetails.capabilities.currentExtent;
|
createInfo.imageExtent = info.swapDetails.capabilities.currentExtent;
|
||||||
createInfo.imageArrayLayers = 1;
|
createInfo.imageArrayLayers = 1;
|
||||||
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
|
||||||
|
uint32_t queueFamilyIndices[] = {info.queueIndices.graphicsFamily.value(), info.queueIndices.presentFamily.value()};
|
||||||
if (info.queueIndices.graphicsFamily != info.queueIndices.presentFamily) {
|
if (info.queueIndices.graphicsFamily != info.queueIndices.presentFamily) {
|
||||||
uint32_t queueFamilyIndices[] = {info.queueIndices.graphicsFamily.value(), info.queueIndices.presentFamily.value()};
|
|
||||||
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
createInfo.queueFamilyIndexCount = 2;
|
createInfo.queueFamilyIndexCount = 2;
|
||||||
createInfo.pQueueFamilyIndices = queueFamilyIndices;
|
createInfo.pQueueFamilyIndices = queueFamilyIndices;
|
||||||
|
@ -66,7 +67,7 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
|
||||||
createInfo.image = images[i];
|
createInfo.image = images[i];
|
||||||
|
|
||||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
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.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
|
@ -111,7 +112,7 @@ std::optional<uint32_t> SwapChain::acquireNextImage(VkSemaphore semaphore, VkFen
|
||||||
imagesInFlight[imageIndex] = fence;
|
imagesInFlight[imageIndex] = fence;
|
||||||
return imageIndex;
|
return imageIndex;
|
||||||
}
|
}
|
||||||
bool SwapChain::presentImage(uint32_t idx, VkQueue queue, VkSemaphore signalSemaphore) {
|
bool SwapChain::presentImage(uint32_t idx, VkSemaphore signalSemaphore) {
|
||||||
VkSemaphore signalSemaphores[] = {signalSemaphore};
|
VkSemaphore signalSemaphores[] = {signalSemaphore};
|
||||||
|
|
||||||
VkPresentInfoKHR presentInfo{};
|
VkPresentInfoKHR presentInfo{};
|
||||||
|
@ -125,7 +126,7 @@ bool SwapChain::presentImage(uint32_t idx, VkQueue queue, VkSemaphore signalSema
|
||||||
presentInfo.pImageIndices = &idx;
|
presentInfo.pImageIndices = &idx;
|
||||||
presentInfo.pResults = nullptr;
|
presentInfo.pResults = nullptr;
|
||||||
|
|
||||||
auto result = vkQueuePresentKHR(queue, &presentInfo);
|
auto result = vkQueuePresentKHR(presentQueue, &presentInfo);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -14,12 +14,13 @@ public:
|
||||||
const std::vector<VkImageView> &getImageViews() { return imageViews; }
|
const std::vector<VkImageView> &getImageViews() { return imageViews; }
|
||||||
|
|
||||||
std::optional<uint32_t> acquireNextImage(VkSemaphore, VkFence);
|
std::optional<uint32_t> acquireNextImage(VkSemaphore, VkFence);
|
||||||
bool presentImage(uint32_t, VkQueue, VkSemaphore);
|
bool presentImage(uint32_t, VkSemaphore);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
|
|
||||||
VkSwapchainKHR chain;
|
VkQueue presentQueue;
|
||||||
|
VkSwapchainKHR chain = VK_NULL_HANDLE;
|
||||||
std::vector<VkImage> images;
|
std::vector<VkImage> images;
|
||||||
std::vector<VkImageView> imageViews;
|
std::vector<VkImageView> imageViews;
|
||||||
std::vector<VkFence> imagesInFlight;
|
std::vector<VkFence> imagesInFlight;
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <volk.h>
|
||||||
|
|
||||||
|
namespace buffer::vk {
|
||||||
|
|
||||||
|
class MemoryArea {
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkDeviceMemory ref;
|
||||||
|
size_t size;
|
||||||
|
std::vector<>
|
||||||
|
};
|
||||||
|
class Buffer {
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::weak_ptr<>
|
||||||
|
VkBuffer ref;
|
||||||
|
|
||||||
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
// Only is mappable
|
||||||
|
void* data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
using namespace world::client;
|
||||||
|
|
||||||
DistantUniverse::DistantUniverse(const connection& ct, const options& opt): Universe(), peer(ct),
|
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() { }
|
DistantUniverse::~DistantUniverse() { }
|
||||||
|
|
||||||
void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
||||||
|
@ -46,11 +46,12 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
||||||
ZoneScopedN("Missing");
|
ZoneScopedN("Missing");
|
||||||
std::vector<chunk_pos> missing;
|
std::vector<chunk_pos> missing;
|
||||||
//TODO: use easy sphere fill
|
//TODO: use easy sphere fill
|
||||||
for (int x = -loadDistance; x <= loadDistance; x++) {
|
const int queryDistance = std::min(loadDistance, serverDistance);
|
||||||
for (int y = -loadDistance; y <= loadDistance; y++) {
|
for (int x = -queryDistance; x <= queryDistance; x++) {
|
||||||
for (int z = -loadDistance; z <= loadDistance; z++) {
|
for (int y = -queryDistance; y <= queryDistance; y++) {
|
||||||
|
for (int z = -queryDistance; z <= queryDistance; z++) {
|
||||||
const auto dist2 = x * x + y * y + z * 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);
|
const auto p = diff + chunk_pos(x, y, z);
|
||||||
if (chunks.inRange(p) && chunks.find(p) == chunks.end()) {
|
if (chunks.inRange(p) && chunks.find(p) == chunks.end()) {
|
||||||
missing.push_back(p);
|
missing.push_back(p);
|
||||||
|
@ -58,7 +59,8 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
|
||||||
}
|
}
|
||||||
}}}
|
}}}
|
||||||
if(!missing.empty()) {
|
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(area.first);
|
||||||
packet.write(missing.data(), missing.size() * sizeof(chunk_pos));
|
packet.write(missing.data(), missing.size() * sizeof(chunk_pos));
|
||||||
peer.send(packet.get(), net::channel_type::RELIABLE);
|
peer.send(packet.get(), net::channel_type::RELIABLE);
|
||||||
|
@ -78,6 +80,11 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
|
||||||
[&](packet_t* packet, channel_type){
|
[&](packet_t* packet, channel_type){
|
||||||
const server_packet_type type = static_cast<server_packet_type>(*packet->data);
|
const server_packet_type type = static_cast<server_packet_type>(*packet->data);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case server_packet_type::CAPABILITIES: {
|
||||||
|
PacketReader(packet).read(serverDistance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case server_packet_type::COMPRESSION: {
|
case server_packet_type::COMPRESSION: {
|
||||||
if(dict.has_value())
|
if(dict.has_value())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -29,7 +29,8 @@ namespace world::client {
|
||||||
|
|
||||||
chunk_pos last_chunk = chunk_pos(INT_MAX);
|
chunk_pos last_chunk = chunk_pos(INT_MAX);
|
||||||
|
|
||||||
int loadDistance;
|
ushort loadDistance;
|
||||||
int keepDistance;
|
ushort keepDistance;
|
||||||
|
ushort serverDistance;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -44,9 +44,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D, typename R>
|
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;
|
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) {
|
switch(event.type) {
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
LOG_D("Client reconnected");
|
LOG_D("Client reconnected");
|
||||||
|
@ -110,6 +110,7 @@ public:
|
||||||
}
|
}
|
||||||
template<typename D>
|
template<typename D>
|
||||||
bool send(client_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
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);
|
return send(type, &data, sizeof(data), channel, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C, typename D, typename R>
|
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;
|
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) {
|
switch(event.type) {
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
case ENET_EVENT_TYPE_CONNECT:
|
||||||
onConnect(event.peer, event.data);
|
onConnect(event.peer, event.data);
|
||||||
|
@ -72,6 +72,7 @@ public:
|
||||||
}
|
}
|
||||||
template<typename D>
|
template<typename D>
|
||||||
bool sendTo(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
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);
|
return sendTo(peer, type, &data, sizeof(data), channel, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,7 @@ public:
|
||||||
}
|
}
|
||||||
template<typename D>
|
template<typename D>
|
||||||
bool send(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
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);
|
return send(peer, type, &data, sizeof(data), channel, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +98,7 @@ public:
|
||||||
}
|
}
|
||||||
template<typename D>
|
template<typename D>
|
||||||
void broadcast(server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
|
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);
|
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
|
/// {area_<chunk_pos>, zstd<chunk rle>} realable
|
||||||
CHUNK = 17,
|
CHUNK = 17,
|
||||||
/// Chunk changes
|
/// 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
|
/// FIXME: to big !!! MAYBE: compress
|
||||||
EDITS = 18,
|
EDITS = 18,
|
||||||
|
|
||||||
/// World compression dictionary
|
/// World compression dictionary
|
||||||
/// zstd dict realable
|
/// zstd dict realable
|
||||||
COMPRESSION = 24,
|
COMPRESSION = 24,
|
||||||
|
/// Server capabilities
|
||||||
|
/// ushort(loadDistance), MAYBE: more realable
|
||||||
|
CAPABILITIES = 25,
|
||||||
};
|
};
|
||||||
enum class client_packet_type: enet_uint8 {
|
enum class client_packet_type: enet_uint8 {
|
||||||
/// Interact with voxels
|
/// Interact with voxels
|
||||||
|
|
|
@ -15,9 +15,9 @@ namespace world {
|
||||||
/// Distance management
|
/// Distance management
|
||||||
struct options {
|
struct options {
|
||||||
/// Radius in chunks to load if missing
|
/// Radius in chunks to load if missing
|
||||||
int loadDistance = 5;
|
ushort loadDistance = 5;
|
||||||
/// Radius in chunks to keep in memory
|
/// Radius in chunks to keep in memory
|
||||||
int keepDistance = 6;
|
ushort keepDistance = 6;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Universe voxel ray intersection
|
/// Universe voxel ray intersection
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
#include "world/SharedUniverse.hpp"
|
#include "world/SharedUniverse.hpp"
|
||||||
#endif
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
Server::Server(config::server::options& options): options(options) {
|
Server::Server(config::server::options& options): options(options), localHandle(options.allowLocal ? new server_handle() : nullptr) { }
|
||||||
//MAYBE: if allow local
|
|
||||||
localHandle = options.allowLocal ? new server_handle() : nullptr;
|
|
||||||
}
|
|
||||||
Server::~Server() { }
|
Server::~Server() { }
|
||||||
|
|
||||||
const auto TPS = 10;
|
const auto TPS = 10;
|
||||||
|
@ -29,9 +27,16 @@ void Server::run() {
|
||||||
signal(SIGINT, handle_signal);
|
signal(SIGINT, handle_signal);
|
||||||
signal(SIGTERM, handle_signal);
|
signal(SIGTERM, handle_signal);
|
||||||
|
|
||||||
|
auto lastTick = std::chrono::steady_clock::now();
|
||||||
while(running && (localHandle == nullptr || localHandle->running)) {
|
while(running && (localHandle == nullptr || localHandle->running)) {
|
||||||
universe->update(1. / TPS); //FIXME: use chrono
|
FrameMarkStart("Server");
|
||||||
FrameMarkNamed("Server");
|
auto startTick = std::chrono::steady_clock::now();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / TPS));
|
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() {
|
void Universe::pullNetwork() {
|
||||||
|
ZoneScopedN("Network");
|
||||||
using namespace net;
|
using namespace net;
|
||||||
host.pull(
|
host.pull(
|
||||||
[&](peer_t *peer, salt_t salt) {
|
[&](peer_t *peer, salt_t salt) {
|
||||||
|
ZoneScopedN("Connect");
|
||||||
LOG_D("Client connect from " << peer->address);
|
LOG_D("Client connect from " << peer->address);
|
||||||
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{ }));
|
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{ }));
|
||||||
peer->data = client;
|
peer->data = client;
|
||||||
|
@ -339,15 +341,18 @@ void Universe::pullNetwork() {
|
||||||
host.sendTo<salt_t>(peer, server_packet_type::CHALLENGE, rnd, channel_type::RELIABLE);
|
host.sendTo<salt_t>(peer, server_packet_type::CHALLENGE, rnd, channel_type::RELIABLE);
|
||||||
client->salt = salt ^ rnd;
|
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);
|
host.send(peer, server_packet_type::COMPRESSION, dict_content.data(), dict_content.size(), channel_type::RELIABLE);
|
||||||
broadcastAreas();
|
broadcastAreas();
|
||||||
},
|
},
|
||||||
[](peer_t *peer, disconnect_reason reason) {
|
[](peer_t *peer, disconnect_reason reason) {
|
||||||
|
ZoneScopedN("Disconnect");
|
||||||
LOG_D("Client disconnect from " << peer->address << " with " << (enet_uint32)reason);
|
LOG_D("Client disconnect from " << peer->address << " with " << (enet_uint32)reason);
|
||||||
if (const auto data = Server::GetPeerData<net_client>(peer); data != nullptr)
|
if (const auto data = Server::GetPeerData<net_client>(peer); data != nullptr)
|
||||||
delete data;
|
delete data;
|
||||||
},
|
},
|
||||||
[&](peer_t *peer, packet_t* packet, channel_type) {
|
[&](peer_t *peer, packet_t* packet, channel_type) {
|
||||||
|
ZoneScopedN("Data");
|
||||||
if(packet->dataLength < sizeof(client_packet_type) + sizeof(salt_t)) {
|
if(packet->dataLength < sizeof(client_packet_type) + sizeof(salt_t)) {
|
||||||
LOG_D("Empty packet from " << peer->address);
|
LOG_D("Empty packet from " << peer->address);
|
||||||
return;
|
return;
|
||||||
|
@ -403,7 +408,7 @@ void Universe::pullNetwork() {
|
||||||
LOG_D("Bad packet from " << peer->address);
|
LOG_D("Bad packet from " << peer->address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, 100);
|
});
|
||||||
}
|
}
|
||||||
void Universe::broadcastAreas() {
|
void Universe::broadcastAreas() {
|
||||||
constexpr size_t ITEM_SIZE = sizeof(area_id) + sizeof(world::Area::params);
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
|
||||||
|
ZoneScopedN("Fill");
|
||||||
ItemList list;
|
ItemList list;
|
||||||
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
if(const auto it = areas.find(pos.first); it != areas.end()) {
|
||||||
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
|
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);
|
size_t size = sizeof(area_id);
|
||||||
for(const auto& part: edits) {
|
for(const auto& part: edits) {
|
||||||
size += sizeof(chunk_pos);
|
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>>>;
|
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
|
data::safe_queue<save_task_t> saveQueue; //NOTE: consider Area and Chunk const
|
||||||
|
|
||||||
int loadDistance;
|
ushort loadDistance;
|
||||||
int keepDistance;
|
ushort keepDistance;
|
||||||
std::string folderPath;
|
std::string folderPath;
|
||||||
|
|
||||||
net::Server host;
|
net::Server host;
|
||||||
|
|
Loading…
Reference in New Issue