1
0
Fork 0

WIP: Vulkan buffers

This commit is contained in:
May B. 2020-09-27 22:25:35 +02:00
parent 41eb636826
commit 3cc8870037
49 changed files with 633 additions and 245 deletions

View File

@ -19,9 +19,10 @@
namespace tracy
{
class VkCtxScope {};
class VkCtx;
}
using TracyVkCtx = void*;
using TracyVkCtx = tracy::VkCtx*;
#else

BIN
resource/content/shaders/Color.fs.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Color.vs.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Sky.fs.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Sky.vs.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)

Binary file not shown.

BIN
resource/content/shaders/Voxel.fs.geo.ins.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.fs.geo.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.fs.ins.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.gs.geo.ins.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.gs.geo.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.vs.geo.ins.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.vs.geo.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.vs.ins.spv (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS) Normal file

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,27 +1,39 @@
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (constant_id = 0) const bool FOG = true;
layout (constant_id = 1) const bool PBR = true;
layout (constant_id = 2) const bool TRIPLANAR = false;
layout (constant_id = 3) const bool STOCHASTIC = false;
layout (constant_id = 4) const bool BLEND = true;
// ...
layout (constant_id = 16) const int UNIT_SIZE = 8;
layout (constant_id = 16) UNIT_SIZE = 8;
layout (binding = 1) uniform sampler2DArray TextureAtlas;
layout (binding = 2) uniform sampler2DArray NormalAtlas;
layout (binding = 3) uniform sampler2DArray HOSAtlas;
// Ouput data
layout(location = 0) out vec3 color;
layout(push_constant) uniform PushConstants {
mat4 Proj;
mat4 View;
#ifndef INSTANCED
mat4 Model;
#endif
uniform sampler2DArray TextureAtlas;
uniform sampler2DArray NormalAtlas;
uniform sampler2DArray HOSAtlas;
vec4 SphereProj;
float Curvature;
uniform mat4 View;
uniform vec3 FogColor;
//MAYBE: extract
vec3 FogColor;
float FogDepth;
vec3 LightInvDirection_worldspace;
} Push;
#ifdef GEOMETRY
in GeometryData
layout (location = 0) in GeometryData
#else
in VertexData
layout (location = 0) in VertexData
#endif
{
vec3 Position_modelspace;
@ -40,6 +52,8 @@ in VertexData
float Depth;
} vs;
layout(location = 0) out vec3 color;
vec3 expand(vec3 v) {
return (v - 0.5) * 2;
}
@ -49,7 +63,7 @@ vec2 hash2D(vec2 s) {
return fract(sin(mod(vec2(dot(s, vec2(127.1, 311.7)), dot(s, vec2(269.5, 183.3))), 3.14159)) * 43758.5453);
}
vec4 textureStochastic(sampler2DArray sample, vec3 UV) {
vec4 textureStochastic(sampler2DArray smpl, vec3 UV) {
if(STOCHASTIC) {
// triangular by approx 2*sqrt(3)
vec2 skewUV = mat2(1.0, 0.0, -0.57735027, 1.15470054) * (UV.xy * 3.46400);
@ -79,46 +93,48 @@ if(STOCHASTIC) {
vec2 dx = dFdx(UV.xy);
vec2 dy = dFdy(UV.xy);
return textureGrad(sample, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
textureGrad(sample, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
return textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx0.xy), UV.z), dx, dy) * BW_vx3.x +
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx1.xy), UV.z), dx, dy) * BW_vx3.y +
textureGrad(smpl, vec3(UV.xy + hash2D(BW_vx2.xy), UV.z), dx, dy) * BW_vx3.z;
} else {
return texture(sample, UV);
return texture(smpl, UV);
}
}
vec4 getTexture(sampler2DArray sample, vec2 UV) {
vec4 getTexture(sampler2DArray smpl, vec2 UV) {
#ifdef GEOMETRY
if(BLEND) {
vec4 colx = textureStochastic(sample, vec3(UV, vs.Textures[0]));
vec4 colx = textureStochastic(smpl, vec3(UV, vs.Textures[0]));
if(vs.Textures[1] == vs.Textures[0]) {
return vs.Textures[2] == vs.Textures[0] ? colx :
mix(colx, textureStochastic(sample, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
mix(colx, textureStochastic(smpl, vec3(UV, vs.Textures[2])), vs.TextureRatio.z);
} else {
vec4 coly = textureStochastic(sample, vec3(UV, vs.Textures[1]));
vec4 coly = textureStochastic(smpl, vec3(UV, vs.Textures[1]));
return vs.Textures[2] == vs.Textures[0] ? mix(colx, coly, vs.TextureRatio.y) : (
vs.Textures[2] == vs.Textures[1] ? mix(coly, colx, vs.TextureRatio.x) :
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochastic(sample, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
colx * vs.TextureRatio.x + coly * vs.TextureRatio.y + textureStochastic(smpl, vec3(UV, vs.Textures[2])) * vs.TextureRatio.z);
}
} else {
int mainTexture = vs.TextureRatio.x >= vs.TextureRatio.y ?
(vs.TextureRatio.x >= vs.TextureRatio.z ? 0 : 2) :
(vs.TextureRatio.y >= vs.TextureRatio.z ? 1 : 2);
return textureStochastic(sample, vec3(UV, vs.Textures[mainTexture]));
return textureStochastic(smpl, vec3(UV, vs.Textures[mainTexture]));
}
#else
return textureStochastic(sample, vec3(UV, vs.Texture));
return textureStochastic(smpl, vec3(UV, vs.Texture));
#endif
}
vec3 getTriTexture(sampler2DArray sample, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(sample, crdx).rgb * weights.x +
getTexture(sample, crdy).rgb * weights.y +
getTexture(sample, crdz).rgb * weights.z;
vec3 getTriTexture(sampler2DArray smpl, vec2 crdx, vec2 crdy, vec2 crdz, vec3 weights) {
return getTexture(smpl, crdx).rgb * weights.x +
getTexture(smpl, crdy).rgb * weights.y +
getTexture(smpl, crdz).rgb * weights.z;
}
void main() {
float texScale = 1. / UNIT_SIZE;
vec3 tex, texN, worldNormal, texHOS;
if(TRIPLANAR) {
// Triplanar
float plateauSize = 0.001;
@ -173,7 +189,7 @@ if(PBR) {
vec3 TextureAmbientColor = vec3(.1) * TextureDiffuseColor * texHOS.y;
vec3 TextureSpecularColor = vec3(.8) * texHOS.z;
vec3 Normal_cameraspace = normalize((View * vec4(worldNormal,0)).xyz);
vec3 Normal_cameraspace = normalize((Push.View * vec4(worldNormal,0)).xyz);
// Light emission properties
// You probably want to put them as uniforms
@ -218,7 +234,7 @@ if(PBR) {
}
if(FOG) {
float ratio = exp(vs.Depth * 0.69)-1;
color = mix(color, pow(FogColor, vec3(2.2)), clamp(ratio, 0, 1));
color = mix(color, pow(Push.FogColor, vec3(2.2)), clamp(ratio, 0, 1));
}
color = pow(color, vec3(1.0 / 2.2));
if(color.r > 1 || color.g > 1 || color.b > 1) {

View File

@ -1,4 +1,5 @@
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (constant_id = 0) const bool FOG = true;
layout (constant_id = 1) const bool PBR = true;
@ -6,7 +7,7 @@ layout (constant_id = 1) const bool PBR = true;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
in VertexData {
layout (location = 0) in VertexData {
vec3 Position_modelspace;
flat uint Texture;
vec3 FaceNormal_modelspace;
@ -18,7 +19,7 @@ in VertexData {
float Depth;
} vs_in[];
out GeometryData {
layout (location = 0) out GeometryData {
vec3 Position_modelspace;
flat uint Textures[3];
vec3 TextureRatio;

View File

@ -1,4 +1,5 @@
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (constant_id = 0) const bool FOG = true;
layout (constant_id = 1) const bool PBR = true;
@ -6,11 +7,32 @@ layout (constant_id = 1) const bool PBR = true;
layout (constant_id = 5) const bool DO_CURVATURE = false;
layout (constant_id = 6) const bool CURV_DEPTH = true;
layout(location = 0) in vec3 Position_modelspace;
layout(location = 1) in uint Texture_model;
layout(location = 2) in vec3 Normal_modelspace;
layout(push_constant) uniform PushConstants {
mat4 Proj;
mat4 View;
#ifndef INSTANCED
mat4 Model;
#endif
out VertexData {
vec4 SphereProj;
float Curvature;
//MAYBE: extract
vec3 FogColor;
float FogDepth;
vec3 LightInvDirection_worldspace;
} Push;
layout (location = 0) in vec3 Position_modelspace;
layout (location = 1) in uint Texture_model;
layout (location = 2) in vec3 Normal_modelspace;
#ifdef INSTANCED
layout (location = 6) in mat4 Model;
#endif
layout (location = 0) out VertexData {
vec3 Position_modelspace;
flat uint Texture;
vec3 FaceNormal_modelspace;
@ -22,47 +44,35 @@ out VertexData {
float Depth;
} vs;
#ifdef INSTANCED
layout(location = 6) in mat4 Model;
#else
uniform mat4 Model;
#endif
uniform mat4 View;
uniform mat4 Proj;
uniform vec4 SphereProj;
uniform float Curvature;
uniform vec3 LightInvDirection_worldspace;
uniform float FogDepth;
void main(){
#ifndef INSTANCED
mat4 Model = Push.Model;
#endif
vs.Position_modelspace = Position_modelspace;
if(DO_CURVATURE) {
if(Curvature > 0) {
vec3 Position_areaspace = Position_modelspace + SphereProj.xyz;
if(Push.Curvature > 0) {
vec3 Position_areaspace = Position_modelspace + Push.SphereProj.xyz;
vec2 sph = vec2(acos(Position_areaspace.z / length(Position_areaspace.xyz)), atan(Position_areaspace.y, Position_areaspace.x));
if(CURV_DEPTH) {
float radius = max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z));
} else {
float radius = SphereProj.w;
}
vs.Position_modelspace = mix(vs.Position_modelspace, vec3(sin(sph.x)*cos(sph.y), sin(sph.x)*sin(sph.y), cos(sph.x)) * radius - SphereProj.xyz, Curvature);
float radius = CURV_DEPTH ?
max(max(abs(Position_areaspace.x), abs(Position_areaspace.y)), abs(Position_areaspace.z)) :
Push.SphereProj.w;
vs.Position_modelspace = mix(vs.Position_modelspace, vec3(sin(sph.x)*cos(sph.y), sin(sph.x)*sin(sph.y), cos(sph.x)) * radius - Push.SphereProj.xyz, Push.Curvature);
}
}
vec4 Position_cameraspace = View * Model * vec4(vs.Position_modelspace, 1);
gl_Position = Proj * Position_cameraspace;
vec4 Position_cameraspace = Push.View * Model * vec4(vs.Position_modelspace, 1);
gl_Position = Push.Proj * Position_cameraspace;
if(FOG) {
vs.Depth = length(Position_cameraspace.xyz) / FogDepth;
vs.Depth = length(Position_cameraspace.xyz) / Push.FogDepth;
}
vs.Texture = Texture_model;
vs.FaceNormal_modelspace = normalize(Normal_modelspace);
if(PBR)
if(PBR) {
// TODO: correct normal curvature
vs.FaceNormal_worldspace = normalize((Model * vec4(vs.FaceNormal_modelspace, 0)).xyz);
@ -71,6 +81,6 @@ if(PBR)
vs.EyeDirection_cameraspace = vec3(0,0,0) - Position_cameraspace.xyz;
// Vector that goes from the vertex to the light, in camera space
vs.LightDirection_cameraspace = (View * vec4(LightInvDirection_worldspace,0)).xyz;
vs.LightDirection_cameraspace = (Push.View * vec4(Push.LightInvDirection_worldspace,0)).xyz;
}
}

View File

@ -2,28 +2,32 @@
BASEDIR=$(dirname "$0")
TARGETDIR="$BASEDIR/../content/shaders"
GLSL="glslc"
rm $TARGETDIR/*.spv
# Tris
glslc -fshader-stage=vertex $BASEDIR/Tris.vs -o $TARGETDIR/Tris.vs.spv
glslc -fshader-stage=fragment $BASEDIR/Tris.fs -o $TARGETDIR/Tris.fs.spv
$GLSL $BASEDIR/Tris.vert -o $TARGETDIR/Tris.vs.spv
$GLSL $BASEDIR/Tris.frag -o $TARGETDIR/Tris.fs.spv
$GLSL $BASEDIR/Tris.vert $BASEDIR/Tris.frag -o $TARGETDIR/Tris.spv
# Color
glslc -fshader-stage=vertex $TARGETDIR/Color.vs -o $TARGETDIR/Color.vs.spv
glslc -fshader-stage=fragment $TARGETDIR/Color.fs -o $TARGETDIR/Color.fs.spv
$GLSL $BASEDIR/Color.vert -o $TARGETDIR/Color.vs.spv
$GLSL $BASEDIR/Color.frag -o $TARGETDIR/Color.fs.spv
# Sky
glslc -fshader-stage=vertex $TARGETDIR/Sky.vs -o $TARGETDIR/Sky.vs.spv
glslc -fshader-stage=fragment $TARGETDIR/Sky.fs -o $TARGETDIR/Sky.fs.spv
$GLSL $BASEDIR/Sky.vert -o $TARGETDIR/Sky.vs.spv
$GLSL $BASEDIR/Sky.frag -o $TARGETDIR/Sky.fs.spv
# Voxel
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -o $TARGETDIR/Voxel.vs.spv
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -o $TARGETDIR/Voxel.fs.spv
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DINSTANCED -o $TARGETDIR/Voxel.fs.ins.spv
$GLSL $BASEDIR/Voxel.vert -o $TARGETDIR/Voxel.vs.spv
$GLSL $BASEDIR/Voxel.frag -o $TARGETDIR/Voxel.fs.spv
$GLSL $BASEDIR/Voxel.vert -DINSTANCED -o $TARGETDIR/Voxel.vs.ins.spv
$GLSL $BASEDIR/Voxel.frag -DINSTANCED -o $TARGETDIR/Voxel.fs.ins.spv
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DGEOMETRY -o $TARGETDIR/Voxel.vs.geo.spv
glslc -fshader-stage=geometry $BASEDIR/Voxel.gs -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
glslc -fshader-stage=vertex $BASEDIR/Voxel.vs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.vs.geo.ins.spv
glslc -fshader-stage=geometry $BASEDIR/Voxel.gs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.gs.geo.ins.spv
glslc -fshader-stage=fragment $BASEDIR/Voxel.fs -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.fs.geo.ins.spv
$GLSL $BASEDIR/Voxel.vert -DGEOMETRY -o $TARGETDIR/Voxel.vs.geo.spv
$GLSL $BASEDIR/Voxel.geom -DGEOMETRY -o $TARGETDIR/Voxel.gs.geo.spv
$GLSL $BASEDIR/Voxel.frag -DGEOMETRY -o $TARGETDIR/Voxel.fs.geo.spv
$GLSL $BASEDIR/Voxel.vert -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.vs.geo.ins.spv
$GLSL $BASEDIR/Voxel.geom -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.gs.geo.ins.spv
$GLSL $BASEDIR/Voxel.frag -DGEOMETRY -DINSTANCED -o $TARGETDIR/Voxel.fs.geo.ins.spv

View File

@ -35,6 +35,7 @@ void Client::run(server_handle* const localHandle) {
//TODO: loop
do {
window.startFrame();
FrameMark;
{ // Update
ZoneScopedN("Update");
static double lastTime = window.getTime();
@ -178,7 +179,6 @@ void Client::run(server_handle* const localHandle) {
ZoneScopedN("Swap");
pipeline->swapBuffer(window);
inputs.poll();
FrameMarkNamed("Client");
}
window.waitTargetFPS();

View File

@ -183,8 +183,16 @@ namespace contouring {
}
void FlatDualMC::onGui() {
ImGui::SliderInt("Load Distance", &loadDistance, 1, keepDistance);
ImGui::SliderInt("Keep Distance", &keepDistance, loadDistance + 1, 21);
{
int load = loadDistance;
ImGui::SliderInt("Load Distance", &load, 1, keepDistance);
loadDistance = load;
}
{
int keep = keepDistance;
ImGui::SliderInt("Keep Distance", &keep, loadDistance + 1, 21);
keepDistance = keep;
}
ImGui::Checkbox("Transparency", &transparency);
ImGui::SliderFloat("Iso", &iso, 0, 1);
ImGui::Checkbox("Manifold", &manifold);

View File

@ -49,8 +49,8 @@ namespace contouring {
void enqueue(const area_<chunk_pos> &, const chunk_pos &offset, const world::ChunkContainer &);
int loadDistance = 3;
int keepDistance = 4;
ushort loadDistance = 3;
ushort keepDistance = 4;
bool transparency = false;
float iso = .1f;
bool manifold = true;

View File

@ -114,8 +114,12 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
if (options.debugMenu.world) {
ImGui::Begin("Debug: World", &options.debugMenu.world, ImGuiWindowFlags_AlwaysAutoResize);
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
int load = options.world.loadDistance;
int keep = options.world.keepDistance;
if (ImGui::SliderInt("Load distance", &load, 1, options.world.keepDistance) |
ImGui::SliderInt("Keep distance", &keep, options.world.loadDistance + 1, 21)) {
options.world.loadDistance = load;
options.world.keepDistance = keep;
actions |= Actions::World;
}
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {

View File

@ -1,31 +1,81 @@
#include "CommandPool.hpp"
#include "shared.hpp"
#include "PhysicalDeviceInfo.hpp"
#include "../Renderer.hpp"
#include <TracyVulkan.hpp>
#include "buffer/VertexData.hpp"
#include <memory.h>
using namespace render::vk;
CommandPool::CommandPool(VkDevice device, const std::vector<VkImageView>& views, PipelineRef pipe, const PhysicalDeviceInfo& info, const renderOptions& opt):
device(device) {
CommandPool::CommandPool(VkDevice device, const std::vector<VkImageView> &views, PipelineRef pipe, const PhysicalDeviceInfo &info, const renderOptions &opt,
VkQueue ctxQueue) : device(device)
{
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
poolInfo.flags = 0; // Optional
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // Optional
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &cmdPool) != VK_SUCCESS) {
FATAL("Failed to create command pool!");
}
allocate(views, pipe, info.swapDetails.capabilities.currentExtent, opt);
{
size_t size = sizeof(buffer::vk::vertices[0]) * buffer::vk::vertices.size();
createAllocatedBuffer(info, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vertexBuffer, vertexBufferMemory);
// Upload
void* data;
vkMapMemory(device, vertexBufferMemory, 0, size, 0, &data);
memcpy(data, buffer::vk::vertices.data(), size);
vkUnmapMemory(device, vertexBufferMemory);
/*
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
memcpy(data, vertices.data(), (size_t) bufferSize);
vkUnmapMemory(device, stagingBufferMemory);
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
*/
}
{
size_t size = sizeof(buffer::vk::indices[0]) * buffer::vk::indices.size();
createAllocatedBuffer(info, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
indexBuffer, indexBufferMemory);
// Upload
void* data;
vkMapMemory(device, indexBufferMemory, 0, size, 0, &data);
memcpy(data, buffer::vk::indices.data(), size);
vkUnmapMemory(device, indexBufferMemory);
}
allocate(views, pipe, info.swapDetails.capabilities.currentExtent, opt, info.device, device, ctxQueue);
}
CommandPool::~CommandPool() {
if(!freed)
free();
vkDestroyCommandPool(device, graphicsPool, ALLOC);
vkDestroyBuffer(device, indexBuffer, ALLOC);
vkFreeMemory(device, indexBufferMemory, ALLOC);
vkDestroyBuffer(device, vertexBuffer, ALLOC);
vkFreeMemory(device, vertexBufferMemory, ALLOC);
vkDestroyCommandPool(device, cmdPool, ALLOC);
}
void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, VkExtent2D extent, const renderOptions& opt) {
void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pipe, VkExtent2D extent, const renderOptions& opt,
VkPhysicalDevice phyDevice, VkDevice device, VkQueue ctxQueue)
{
assert(freed);
framebuffers.resize(views.size());
@ -47,25 +97,28 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
}
}
graphicsBuffers.resize(framebuffers.size());
cmdBuffers.resize(framebuffers.size());
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = graphicsPool;
allocInfo.commandPool = cmdPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = (uint32_t) graphicsBuffers.size();
allocInfo.commandBufferCount = (uint32_t) cmdBuffers.size();
if (vkAllocateCommandBuffers(device, &allocInfo, graphicsBuffers.data()) != VK_SUCCESS) {
if (vkAllocateCommandBuffers(device, &allocInfo, cmdBuffers.data()) != VK_SUCCESS) {
FATAL("Failed to allocate command buffers!");
}
for (size_t i = 0; i < graphicsBuffers.size(); i++) {
tracyCtx.resize(cmdBuffers.size());
for (size_t i = 0; i < cmdBuffers.size(); i++) {
tracyCtx[i] = TracyVkContext(phyDevice, device, ctxQueue, cmdBuffers[i]);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr;
if (vkBeginCommandBuffer(graphicsBuffers[i], &beginInfo) != VK_SUCCESS) {
if (vkBeginCommandBuffer(cmdBuffers[i], &beginInfo) != VK_SUCCESS) {
FATAL("Failed to begin recording command buffer!");
}
@ -80,12 +133,16 @@ void CommandPool::allocate(const std::vector<VkImageView>& views, PipelineRef pi
renderPassInfo.clearValueCount = 1; //TODO: clear depth
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
vkCmdDraw(graphicsBuffers[i], 3, 1, 0, 0);
vkCmdEndRenderPass(graphicsBuffers[i]);
vkCmdBeginRenderPass(cmdBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.second);
VkBuffer vertexBuffers[] = {vertexBuffer};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(cmdBuffers[i], 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(cmdBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdDrawIndexed(cmdBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(cmdBuffers[i]);
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
if (vkEndCommandBuffer(cmdBuffers[i]) != VK_SUCCESS) {
FATAL("Failed to record command buffer!");
}
}
@ -98,7 +155,12 @@ void CommandPool::free() {
vkDestroyFramebuffer(device, framebuffers[i], nullptr);
}
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
#if TRACY_ENABLE
for (auto ctx : tracyCtx) {
TracyVkDestroy(ctx);
}
#endif
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(cmdBuffers.size()), cmdBuffers.data());
freed = true;
}
@ -106,6 +168,9 @@ void CommandPool::free() {
void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
assert(!freed);
TracyVkCollect(tracyCtx[idx], cmdBuffers[idx]);
//TracyVkZone(tracyCtx[idx], graphicsBuffers[idx], "Submit");
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@ -116,7 +181,7 @@ void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphor
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &graphicsBuffers[idx];
submitInfo.pCommandBuffers = &cmdBuffers[idx];
VkSemaphore signalSemaphores[] = {signalSemaphore};
submitInfo.signalSemaphoreCount = 1;
@ -126,4 +191,69 @@ void CommandPool::submitGraphics(uint32_t idx, VkQueue graphicsQueue, VkSemaphor
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, submittedFence) != VK_SUCCESS) {
FATAL("Failed to submit draw command buffer!");
}
}
}
void CommandPool::createAllocatedBuffer(const PhysicalDeviceInfo& info, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(device, &bufferInfo, ALLOC, &buffer) != VK_SUCCESS) {
FATAL("Failed to create buffer!");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
if (const auto memIdx = info.findMemory(memRequirements.memoryTypeBits, properties)) {
allocInfo.memoryTypeIndex = memIdx.value();
} else {
FATAL("No available memory heap");
}
if (vkAllocateMemory(device, &allocInfo, ALLOC, &bufferMemory) != VK_SUCCESS) {
FATAL("Failed to allocate buffer memory!");
}
vkBindBufferMemory(device, buffer, bufferMemory, 0);
}
/*void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkBufferCopy copyRegion{};
copyRegion.srcOffset = 0; // Optional
copyRegion.dstOffset = 0; // Optional
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(graphicsQueue);
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
}*/

View File

@ -3,27 +3,40 @@
#include "forward.hpp"
#include <vector>
namespace tracy {
class VkCtx;
}
typedef tracy::VkCtx* TracyVkCtx;
namespace render::vk {
class SwapChain;
class Pipeline;
class CommandPool {
public:
CommandPool(VkDevice, const std::vector<VkImageView>&, PipelineRef, const PhysicalDeviceInfo&, const renderOptions&);
CommandPool(VkDevice, const std::vector<VkImageView>&, PipelineRef, const PhysicalDeviceInfo&, const renderOptions&, VkQueue);
~CommandPool();
void submitGraphics(uint32_t, VkQueue, VkSemaphore, VkSemaphore, VkFence);
void allocate(const std::vector<VkImageView>&, PipelineRef, VkExtent2D, const renderOptions&);
void allocate(const std::vector<VkImageView> &, PipelineRef, VkExtent2D, const renderOptions &, VkPhysicalDevice, VkDevice, VkQueue);
void free();
void createAllocatedBuffer(const PhysicalDeviceInfo&, VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags, VkBuffer&, VkDeviceMemory&);
private:
VkDevice device;
std::vector<VkFramebuffer> framebuffers;
VkCommandPool graphicsPool;
std::vector<VkCommandBuffer> graphicsBuffers;
VkCommandPool cmdPool;
std::vector<VkCommandBuffer> cmdBuffers;
std::vector<TracyVkCtx> tracyCtx;
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
bool freed = true;
};
}

View File

@ -0,0 +1,88 @@
#include "PhysicalDeviceInfo.hpp"
using namespace render::vk;
SwapChainSupportDetails SwapChainSupportDetails::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
SwapChainSupportDetails swapDetails;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapDetails.capabilities);
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0) {
swapDetails.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapDetails.formats.data());
}
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if (presentModeCount != 0) {
swapDetails.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapDetails.presentModes.data());
}
return swapDetails;
}
QueueFamilyIndices QueueFamilyIndices::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
QueueFamilyIndices queueIndices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for(const auto& queueFamily: queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
queueIndices.graphicsFamily = i;
} else if (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) {
queueIndices.transferFamily = i;
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if (presentSupport) {
queueIndices.presentFamily = i;
}
#if DEBUG
LOG_D("Queue " << i << ' ' << (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT ? "graphics " : "")
<< (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT ? "compute " : "")
<< (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT ? "transfer " : "")
<< (queueFamily.queueFlags & VK_QUEUE_PROTECTED_BIT ? "protected " : "")
<< 'x' << queueFamily.queueCount);
#endif
i++;
}
return queueIndices;
}
VkSurfaceFormatKHR PhysicalDeviceInfo::getFormat() const {
for(const auto& format: swapDetails.formats) {
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return format;
}
}
LOG_W("Using suboptimal surface format");
return swapDetails.formats[0];
}
std::optional<uint32_t> PhysicalDeviceInfo::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags properties) const {
#if DEBUG
LOG_D("available memory:");
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
LOG_D('\t' << i << ": " << ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ? "local " : "")
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ? "visible " : "")
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) ? "coherent " : "")
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) ? "cached " : "")
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) ? "lazy " : "")
<< ((memProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_PROTECTED_BIT) ? "protected " : "")
<< memProperties.memoryHeaps[memProperties.memoryTypes[i].heapIndex].size);
}
#endif
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
return {};
}

View File

@ -17,15 +17,29 @@ struct SwapChainSupportDetails {
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
std::optional<uint32_t> transferFamily;
static QueueFamilyIndices Query(VkPhysicalDevice, VkSurfaceKHR);
bool isComplete() const { return graphicsFamily.has_value() && presentFamily.has_value(); }
bool isOptimal() const { return isComplete() && transferFamily.has_value(); }
};
struct PhysicalDeviceInfo {
VkPhysicalDevice device = VK_NULL_HANDLE;
PhysicalDeviceInfo() {}
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface):
window(window), device(device), surface(surface),
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface))
{
vkGetPhysicalDeviceMemoryProperties(device, &memProperties);
}
VkSurfaceFormatKHR getFormat() const;
std::optional<uint32_t> findMemory(uint32_t, VkMemoryPropertyFlags) const;
GLFWwindow *window;
VkPhysicalDevice device = VK_NULL_HANDLE;
VkSurfaceKHR surface;
SwapChainSupportDetails swapDetails;
QueueFamilyIndices queueIndices;
VkSurfaceFormatKHR surfaceFormat;
VkSurfaceKHR surface;
VkPhysicalDeviceMemoryProperties memProperties;
//MAYBE: add limits memory infos
};
}

View File

@ -1,8 +1,9 @@
#include "Pipeline.hpp"
#include "shared.hpp"
#include "PhysicalDeviceInfo.hpp"
#include "../../../core/data/file.hpp"
#include "../Renderer.hpp"
#include "buffer/VertexData.hpp"
#define CONTENT_DIR "content/"
#define SHADER_DIR CONTENT_DIR "shaders/"
@ -15,7 +16,7 @@ using namespace render::vk;
Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const renderOptions &options): device(device) {
{ // Render pass
VkAttachmentDescription colorAttachment{};
colorAttachment.format = info.surfaceFormat.format;
colorAttachment.format = info.getFormat().format;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@ -110,10 +111,13 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexBindingDescriptions = nullptr; // TODO: uniforms, and buffers
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.pVertexAttributeDescriptions = nullptr; // TODO: uniforms, and buffers
auto bindingDescription = buffer::vk::VertexData::getBindingDescription();
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
auto attributeDescriptions = buffer::vk::VertexData::getAttributeDescriptions();
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;

View File

@ -2,7 +2,7 @@
#include "UI.hpp"
#include "../../Window.hpp"
#include "shared.hpp"
#include "PhysicalDeviceInfo.hpp"
#include "SwapChain.hpp"
#include "Pipeline.hpp"
#include "CommandPool.hpp"
@ -23,22 +23,14 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf
physicalInfo(std::make_unique<PhysicalDeviceInfo>(info)) {
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue);
if(info.queueIndices.transferFamily.has_value())
vkGetDeviceQueue(device, info.queueIndices.transferFamily.value(), 0, &transferQueue.value());
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
physicalInfo->surfaceFormat = [&]() {
for(const auto& format: info.swapDetails.formats) {
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return format;
}
}
LOG_W("Using suboptimal surface format");
return info.swapDetails.formats[0];
}();
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
commandPool = std::make_unique<CommandPool>(device, swapChain->getImageViews(), pipeline->getRef(), *physicalInfo.get(), options);
commandPool = std::make_unique<CommandPool>(device, swapChain->getImageViews(), pipeline->getRef(), *physicalInfo.get(), options, graphicsQueue);
{
imageAvailableSemaphores.resize(opt.inFlightFrames);
@ -81,7 +73,6 @@ Renderer::~Renderer() {
}
void Renderer::recreateSwapChain() {
LOG_D("Recreating swapchain");
vkDeviceWaitIdle(device);
destroySwapChain();
@ -89,7 +80,8 @@ void Renderer::recreateSwapChain() {
set_current_extent(physicalInfo->swapDetails.capabilities, physicalInfo->window);
swapChain = std::make_unique<SwapChain>(device, *physicalInfo.get());
pipeline = std::make_unique<Pipeline>(device, *physicalInfo.get(), options);
commandPool->allocate(swapChain->getImageViews(), pipeline->getRef(), physicalInfo->swapDetails.capabilities.currentExtent, options);
commandPool->allocate(swapChain->getImageViews(), pipeline->getRef(), physicalInfo->swapDetails.capabilities.currentExtent, options,
physicalInfo->device, device, graphicsQueue);
}
void Renderer::destroySwapChain() {
commandPool->free();
@ -266,12 +258,11 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
score += deviceProperties.limits.maxImageDimension2D;
//TODO: check others limits
auto infos = PhysicalDeviceInfo{device, window.getPtr(),
SwapChainSupportDetails::Query(device, surface), QueueFamilyIndices::Query(device, surface),
VkSurfaceFormatKHR(), surface};
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface);
if (!infos.queueIndices.isComplete())
continue;
if (infos.queueIndices.isOptimal())
score += 5000;
if (!infos.swapDetails.isValid())
continue;
@ -339,57 +330,6 @@ void Renderer::loadUI(Window& w) {
UI::Load(w);
}
SwapChainSupportDetails SwapChainSupportDetails::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
SwapChainSupportDetails swapDetails;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &swapDetails.capabilities);
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0) {
swapDetails.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, swapDetails.formats.data());
}
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if (presentModeCount != 0) {
swapDetails.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, swapDetails.presentModes.data());
}
return swapDetails;
}
QueueFamilyIndices QueueFamilyIndices::Query(VkPhysicalDevice device, VkSurfaceKHR surface) {
QueueFamilyIndices queueIndices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for(const auto& queueFamily: queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
queueIndices.graphicsFamily = i;
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if (presentSupport) {
queueIndices.presentFamily = i;
}
#if DEBUG
LOG_D("Queue " << i << ' ' << (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT ? "graphics " : "")
<< (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT ? "compute " : "")
<< (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT ? "transfer " : "")
<< (queueFamily.queueFlags & VK_QUEUE_PROTECTED_BIT ? "protected " : "")
<< 'x' << queueFamily.queueCount);
#endif
i++;
}
return queueIndices;
}
void Renderer::beginFrame() {
assert(currentImage == UINT32_MAX);
@ -436,10 +376,6 @@ void Renderer::endPass() {
}
void Renderer::swapBuffer(Window&) {
/*TracyGpuZone("Swap");
glfwSwapBuffers(ptr);
TracyGpuCollect;*/
if(!swapChain->presentImage(currentImage, presentQueue, renderFinishedSemaphores[currentFrame]) || framebufferResized) {
framebufferResized = false;
recreateSwapChain();

View File

@ -45,6 +45,7 @@ private:
VkDevice device;
VkQueue graphicsQueue;
VkQueue presentQueue;
std::optional<VkQueue> transferQueue;
std::unique_ptr<PhysicalDeviceInfo> physicalInfo;
std::unique_ptr<SwapChain> swapChain;

View File

@ -1,6 +1,6 @@
#include "SwapChain.hpp"
#include "shared.hpp"
#include "PhysicalDeviceInfo.hpp"
using namespace render::vk;
@ -26,8 +26,8 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = info.surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = info.surfaceFormat.format;
createInfo.imageColorSpace = info.surfaceFormat.colorSpace;
createInfo.imageFormat = info.getFormat().format;
createInfo.imageColorSpace = info.getFormat().colorSpace;
createInfo.imageExtent = info.swapDetails.capabilities.currentExtent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ -66,7 +66,7 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de
createInfo.image = images[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = info.surfaceFormat.format;
createInfo.format = info.getFormat().format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;

View File

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

View File

@ -12,7 +12,7 @@
using namespace world::client;
DistantUniverse::DistantUniverse(const connection& ct, const options& opt): Universe(), peer(ct),
loadDistance(opt.loadDistance), keepDistance(opt.keepDistance) { }
loadDistance(opt.loadDistance), keepDistance(opt.keepDistance), serverDistance(0) { }
DistantUniverse::~DistantUniverse() { }
void DistantUniverse::update(voxel_pos pos, float deltaTime) {
@ -46,11 +46,12 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
ZoneScopedN("Missing");
std::vector<chunk_pos> missing;
//TODO: use easy sphere fill
for (int x = -loadDistance; x <= loadDistance; x++) {
for (int y = -loadDistance; y <= loadDistance; y++) {
for (int z = -loadDistance; z <= loadDistance; z++) {
const int queryDistance = std::min(loadDistance, serverDistance);
for (int x = -queryDistance; x <= queryDistance; x++) {
for (int y = -queryDistance; y <= queryDistance; y++) {
for (int z = -queryDistance; z <= queryDistance; z++) {
const auto dist2 = x * x + y * y + z * z;
if (dist2 <= loadDistance * loadDistance) {
if (dist2 <= queryDistance * queryDistance) {
const auto p = diff + chunk_pos(x, y, z);
if (chunks.inRange(p) && chunks.find(p) == chunks.end()) {
missing.push_back(p);
@ -58,7 +59,8 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) {
}
}}}
if(!missing.empty()) {
auto packet = net::Client::makePacket(net::client_packet_type::MISSING_CHUNKS, NULL, sizeof(area_id) + missing.size() * sizeof(chunk_pos), ENET_PACKET_FLAG_RELIABLE, peer.getSalt());
auto packet = net::Client::makePacket(net::client_packet_type::MISSING_CHUNKS, NULL,
sizeof(area_id) + missing.size() * sizeof(chunk_pos), ENET_PACKET_FLAG_RELIABLE, peer.getSalt());
packet.write(area.first);
packet.write(missing.data(), missing.size() * sizeof(chunk_pos));
peer.send(packet.get(), net::channel_type::RELIABLE);
@ -78,6 +80,11 @@ void DistantUniverse::pullNetwork(voxel_pos pos) {
[&](packet_t* packet, channel_type){
const server_packet_type type = static_cast<server_packet_type>(*packet->data);
switch (type) {
case server_packet_type::CAPABILITIES: {
PacketReader(packet).read(serverDistance);
break;
}
case server_packet_type::COMPRESSION: {
if(dict.has_value())
break;

View File

@ -29,7 +29,8 @@ namespace world::client {
chunk_pos last_chunk = chunk_pos(INT_MAX);
int loadDistance;
int keepDistance;
ushort loadDistance;
ushort keepDistance;
ushort serverDistance;
};
}

View File

@ -44,9 +44,9 @@ public:
}
template<typename D, typename R>
void pull(R onData, D onDisconnect, int delay = 0) {
void pull(R onData, D onDisconnect, int delay = 0, int count = 10) {
ENetEvent event;
while(enet_host_service(host, &event, delay) > 0) {
for(int i = 0; i < count && enet_host_service(host, &event, delay) > 0; i++) {
switch(event.type) {
case ENET_EVENT_TYPE_CONNECT:
LOG_D("Client reconnected");
@ -110,6 +110,7 @@ public:
}
template<typename D>
bool send(client_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
static_assert(!std::is_pointer<D>::value);
return send(type, &data, sizeof(data), channel, flags);
}

View File

@ -27,9 +27,9 @@ public:
}
template<typename C, typename D, typename R>
void pull(C onConnect, D onDisconnect, R onData, int delay = 0) {
void pull(C onConnect, D onDisconnect, R onData, int delay = 10, int count = 10) {
ENetEvent event;
while(enet_host_service(host, &event, delay) > 0) {
for(int i = 0; i < count && enet_host_service(host, &event, delay) > 0; i++) {
switch(event.type) {
case ENET_EVENT_TYPE_CONNECT:
onConnect(event.peer, event.data);
@ -72,6 +72,7 @@ public:
}
template<typename D>
bool sendTo(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
static_assert(!std::is_pointer<D>::value);
return sendTo(peer, type, &data, sizeof(data), channel, flags);
}
@ -84,6 +85,7 @@ public:
}
template<typename D>
bool send(peer_t* peer, server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
static_assert(!std::is_pointer<D>::value);
return send(peer, type, &data, sizeof(data), channel, flags);
}
@ -96,6 +98,7 @@ public:
}
template<typename D>
void broadcast(server_packet_type type, const D& data, channel_type channel, std::optional<enet_uint32> flags = {}) {
static_assert(!std::is_pointer<D>::value);
broadcast(type, &data, sizeof(data), channel, flags);
}

View File

@ -37,13 +37,16 @@ enum class server_packet_type: enet_uint8 {
/// {area_<chunk_pos>, zstd<chunk rle>} realable
CHUNK = 17,
/// Chunk changes
/// {area_id, {chunk_pos, short(count), Chunk::Edit[]}[]} notify
/// {area_id, {chunk_pos, ushort(count), Chunk::Edit[]}[]} notify
/// FIXME: to big !!! MAYBE: compress
EDITS = 18,
/// World compression dictionary
/// zstd dict realable
COMPRESSION = 24,
/// Server capabilities
/// ushort(loadDistance), MAYBE: more realable
CAPABILITIES = 25,
};
enum class client_packet_type: enet_uint8 {
/// Interact with voxels

View File

@ -15,9 +15,9 @@ namespace world {
/// Distance management
struct options {
/// Radius in chunks to load if missing
int loadDistance = 5;
ushort loadDistance = 5;
/// Radius in chunks to keep in memory
int keepDistance = 6;
ushort keepDistance = 6;
};
/// Universe voxel ray intersection

View File

@ -4,11 +4,9 @@
#include "world/SharedUniverse.hpp"
#endif
#include <signal.h>
#include <chrono>
Server::Server(config::server::options& options): options(options) {
//MAYBE: if allow local
localHandle = options.allowLocal ? new server_handle() : nullptr;
}
Server::Server(config::server::options& options): options(options), localHandle(options.allowLocal ? new server_handle() : nullptr) { }
Server::~Server() { }
const auto TPS = 10;
@ -29,9 +27,16 @@ void Server::run() {
signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);
auto lastTick = std::chrono::steady_clock::now();
while(running && (localHandle == nullptr || localHandle->running)) {
universe->update(1. / TPS); //FIXME: use chrono
FrameMarkNamed("Server");
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / TPS));
FrameMarkStart("Server");
auto startTick = std::chrono::steady_clock::now();
const std::chrono::duration<float, std::ratio<1>> deltaTime = startTick - lastTick;
universe->update(deltaTime.count());
FrameMarkEnd("Server");
while (std::chrono::steady_clock::now() < startTick + std::chrono::milliseconds(1000 / TPS)) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
lastTick = startTick;
}
}

View File

@ -328,9 +328,11 @@ struct net_client {
};
void Universe::pullNetwork() {
ZoneScopedN("Network");
using namespace net;
host.pull(
[&](peer_t *peer, salt_t salt) {
ZoneScopedN("Connect");
LOG_D("Client connect from " << peer->address);
net_client* client = new net_client(salt, entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{ }));
peer->data = client;
@ -339,15 +341,18 @@ void Universe::pullNetwork() {
host.sendTo<salt_t>(peer, server_packet_type::CHALLENGE, rnd, channel_type::RELIABLE);
client->salt = salt ^ rnd;
host.send(peer, server_packet_type::CAPABILITIES, loadDistance, channel_type::RELIABLE);
host.send(peer, server_packet_type::COMPRESSION, dict_content.data(), dict_content.size(), channel_type::RELIABLE);
broadcastAreas();
},
[](peer_t *peer, disconnect_reason reason) {
ZoneScopedN("Disconnect");
LOG_D("Client disconnect from " << peer->address << " with " << (enet_uint32)reason);
if (const auto data = Server::GetPeerData<net_client>(peer); data != nullptr)
delete data;
},
[&](peer_t *peer, packet_t* packet, channel_type) {
ZoneScopedN("Data");
if(packet->dataLength < sizeof(client_packet_type) + sizeof(salt_t)) {
LOG_D("Empty packet from " << peer->address);
return;
@ -403,7 +408,7 @@ void Universe::pullNetwork() {
LOG_D("Bad packet from " << peer->address);
break;
}
}, 100);
});
}
void Universe::broadcastAreas() {
constexpr size_t ITEM_SIZE = sizeof(area_id) + sizeof(world::Area::params);
@ -453,6 +458,7 @@ std::optional<world::Item> Universe::set(const area_<voxel_pos>& pos, const Voxe
return {};
}
world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val, int radius) {
ZoneScopedN("Fill");
ItemList list;
if(const auto it = areas.find(pos.first); it != areas.end()) {
robin_hood::unordered_map<chunk_pos, std::vector<Chunk::Edit>> edits;
@ -476,6 +482,7 @@ world::ItemList Universe::setCube(const area_<voxel_pos>& pos, const Voxel& val,
}
}
}}}
ZoneScopedN("Packet");
size_t size = sizeof(area_id);
for(const auto& part: edits) {
size += sizeof(chunk_pos);

View File

@ -98,8 +98,8 @@ namespace world::server {
using save_task_t = std::pair<area_it_t, robin_hood::pair<chunk_pos, std::shared_ptr<world::server::Chunk>>>;
data::safe_queue<save_task_t> saveQueue; //NOTE: consider Area and Chunk const
int loadDistance;
int keepDistance;
ushort loadDistance;
ushort keepDistance;
std::string folderPath;
net::Server host;