WIP: Vulkan skybox (bug on intel mesa ???)
This commit is contained in:
parent
07d12b3452
commit
a774e99d7b
BIN
resource/content/shaders/Sky.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Sky.vs.spv (Stored with Git LFS)
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.
BIN
resource/content/shaders/Voxel.fs.geo.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.geo.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.geo.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.geo.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.fs.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.geo.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.geo.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.geo.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.geo.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.ins.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.ins.spv (Stored with Git LFS)
Binary file not shown.
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
BIN
resource/content/shaders/Voxel.vs.spv (Stored with Git LFS)
Binary file not shown.
|
@ -1,9 +1,9 @@
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
layout(binding = 0) uniform UniformBufferObject {
|
||||||
mat4 View;
|
mat4 view;
|
||||||
mat4 Projection;
|
mat4 proj;
|
||||||
} Push;
|
} ubo;
|
||||||
|
|
||||||
layout (location = 0) in vec3 Position_modelspace;
|
layout (location = 0) in vec3 Position_modelspace;
|
||||||
|
|
||||||
|
@ -11,5 +11,7 @@ layout (location = 0) out vec3 UV;
|
||||||
|
|
||||||
void main(){
|
void main(){
|
||||||
UV = Position_modelspace;
|
UV = Position_modelspace;
|
||||||
gl_Position = (Push.Projection * Push.View * vec4(Position_modelspace, 1.0)).xyww;
|
mat4 view = ubo.view;
|
||||||
|
view[3] = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
gl_Position = (ubo.proj * view * vec4(Position_modelspace, 1.0)).xyww;
|
||||||
}
|
}
|
|
@ -2,10 +2,12 @@
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
layout(binding = 0) uniform UniformBufferObject {
|
layout(binding = 0) uniform UniformBufferObject {
|
||||||
mat4 model;
|
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
} ubo;
|
} ubo;
|
||||||
|
layout(push_constant) uniform PushConst {
|
||||||
|
mat4 model;
|
||||||
|
} Push;
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
layout(location = 1) in vec3 inColor;
|
layout(location = 1) in vec3 inColor;
|
||||||
|
@ -15,7 +17,7 @@ layout(location = 0) out vec3 fragColor;
|
||||||
layout(location = 1) out vec2 fragTexCoord;
|
layout(location = 1) out vec2 fragTexCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
|
gl_Position = ubo.proj * ubo.view * Push.model * vec4(inPosition, 1.0);
|
||||||
fragColor = inColor;
|
fragColor = inColor;
|
||||||
fragTexCoord = inTexCoord;
|
fragTexCoord = inTexCoord;
|
||||||
}
|
}
|
|
@ -10,26 +10,18 @@ layout (constant_id = 4) const bool BLEND = true;
|
||||||
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
layout (constant_id = 16) const int UNIT_SIZE = 8;
|
||||||
|
|
||||||
layout (binding = 0) uniform UniformBufferObject {
|
layout (binding = 0) uniform UniformBufferObject {
|
||||||
vec3 FogColor;
|
mat4 Proj;
|
||||||
float FogDepth;
|
mat4 View;
|
||||||
|
|
||||||
vec3 LightInvDirection_worldspace;
|
vec3 LightInvDirection_worldspace;
|
||||||
|
|
||||||
|
vec3 FogColor;
|
||||||
|
float FogDepth;
|
||||||
} UBO;
|
} UBO;
|
||||||
layout (binding = 1) uniform sampler2DArray TextureAtlas;
|
layout (binding = 1) uniform sampler2DArray TextureAtlas;
|
||||||
layout (binding = 2) uniform sampler2DArray NormalAtlas;
|
layout (binding = 2) uniform sampler2DArray NormalAtlas;
|
||||||
layout (binding = 3) uniform sampler2DArray HOSAtlas;
|
layout (binding = 3) uniform sampler2DArray HOSAtlas;
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
|
||||||
mat4 Proj;
|
|
||||||
mat4 View;
|
|
||||||
#ifndef INSTANCED
|
|
||||||
mat4 Model;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec4 SphereProj;
|
|
||||||
float Curvature;
|
|
||||||
} Push;
|
|
||||||
|
|
||||||
#ifdef GEOMETRY
|
#ifdef GEOMETRY
|
||||||
layout (location = 0) in GeometryData
|
layout (location = 0) in GeometryData
|
||||||
#else
|
#else
|
||||||
|
@ -189,7 +181,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((Push.View * vec4(worldNormal,0)).xyz);
|
vec3 Normal_cameraspace = normalize((UBO.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
|
||||||
|
|
|
@ -8,15 +8,16 @@ 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 (binding = 0) uniform UniformBufferObject {
|
layout (binding = 0) uniform UniformBufferObject {
|
||||||
vec3 FogColor;
|
mat4 Proj;
|
||||||
float FogDepth;
|
mat4 View;
|
||||||
|
|
||||||
vec3 LightInvDirection_worldspace;
|
vec3 LightInvDirection_worldspace;
|
||||||
|
|
||||||
|
vec3 FogColor;
|
||||||
|
float FogDepth;
|
||||||
} UBO;
|
} UBO;
|
||||||
|
|
||||||
layout(push_constant) uniform PushConstants {
|
layout(push_constant) uniform PushConstants {
|
||||||
mat4 Proj; //MAYBE: move Proj View to UBO
|
|
||||||
mat4 View;
|
|
||||||
#ifndef INSTANCED
|
#ifndef INSTANCED
|
||||||
mat4 Model;
|
mat4 Model;
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,8 +64,8 @@ if(DO_CURVATURE) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 Position_cameraspace = Push.View * Model * vec4(vs.Position_modelspace, 1);
|
vec4 Position_cameraspace = UBO.View * Model * vec4(vs.Position_modelspace, 1);
|
||||||
gl_Position = Push.Proj * Position_cameraspace;
|
gl_Position = UBO.Proj * Position_cameraspace;
|
||||||
|
|
||||||
if(FOG) {
|
if(FOG) {
|
||||||
vs.Depth = length(Position_cameraspace.xyz) / UBO.FogDepth;
|
vs.Depth = length(Position_cameraspace.xyz) / UBO.FogDepth;
|
||||||
|
@ -82,6 +83,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 = (Push.View * vec4(UBO.LightInvDirection_worldspace,0)).xyz;
|
vs.LightDirection_cameraspace = (UBO.View * vec4(UBO.LightInvDirection_worldspace,0)).xyz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ void Client::run(server_handle* const localHandle) {
|
||||||
auto world = world::client::Load(options.connection, localHandle, options.world, options.contouring);
|
auto world = world::client::Load(options.connection, localHandle, options.world, options.contouring);
|
||||||
state.contouring = world->getContouring();
|
state.contouring = world->getContouring();
|
||||||
|
|
||||||
//TODO: loop
|
|
||||||
do {
|
do {
|
||||||
window.startFrame();
|
window.startFrame();
|
||||||
FrameMark;
|
FrameMark;
|
||||||
|
@ -131,9 +130,8 @@ void Client::run(server_handle* const localHandle) {
|
||||||
{ // Chunks
|
{ // Chunks
|
||||||
const auto pass = pipeline->beginWorldPass();
|
const auto pass = pipeline->beginWorldPass();
|
||||||
const auto draw = [&](glm::mat4 model, render::LodModel *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
|
const auto draw = [&](glm::mat4 model, render::LodModel *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
|
||||||
pipeline->setCurvature(glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
|
|
||||||
reports.models_count++;
|
reports.models_count++;
|
||||||
reports.tris_count += pass(buffer, model);
|
reports.tris_count += pass(buffer, model, glm::vec4(pos, std::get<1>(area)), std::get<2>(area));
|
||||||
};
|
};
|
||||||
if (options.culling > 0) {
|
if (options.culling > 0) {
|
||||||
std::vector<glm::vec3> occlusion;
|
std::vector<glm::vec3> occlusion;
|
||||||
|
@ -166,9 +164,9 @@ void Client::run(server_handle* const localHandle) {
|
||||||
reports.models_count++;
|
reports.models_count++;
|
||||||
reports.tris_count += pipeline->drawIndicatorCube(model);
|
reports.tris_count += pipeline->drawIndicatorCube(model);
|
||||||
}
|
}
|
||||||
pipeline->endPass();
|
pipeline->postProcess();
|
||||||
|
|
||||||
render::UI::Get()->render();
|
render::UI::Get()->render();
|
||||||
|
pipeline->endFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Swap buffers
|
{ // Swap buffers
|
||||||
|
|
|
@ -14,6 +14,7 @@ void Camera::updateProjection() {
|
||||||
|
|
||||||
void Camera::update() {
|
void Camera::update() {
|
||||||
const auto &offset = origin->position.offset;
|
const auto &offset = origin->position.offset;
|
||||||
|
// FIXME: up inverted after backflip
|
||||||
const auto axis = origin->getAxis();
|
const auto axis = origin->getAxis();
|
||||||
// Camera matrix
|
// Camera matrix
|
||||||
ViewMatrix = glm::lookAt(
|
ViewMatrix = glm::lookAt(
|
||||||
|
|
|
@ -64,13 +64,16 @@ public:
|
||||||
/// Start new frame and setup
|
/// Start new frame and setup
|
||||||
virtual void beginFrame() = 0;
|
virtual void beginFrame() = 0;
|
||||||
/// Get started world program
|
/// Get started world program
|
||||||
virtual std::function<size_t(render::LodModel *const, glm::mat4)> beginWorldPass() = 0;
|
/// (vertex buffer, model matrix, sphereProj, curvature)
|
||||||
|
virtual std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass() = 0;
|
||||||
/// Get started entity program
|
/// Get started entity program
|
||||||
virtual std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() = 0;
|
virtual std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() = 0;
|
||||||
/// Draw cube indicator
|
/// Draw cube indicator
|
||||||
virtual size_t drawIndicatorCube(glm::mat4 model) = 0;
|
virtual size_t drawIndicatorCube(glm::mat4 model) = 0;
|
||||||
/// Apply postprocessing
|
/// Apply postprocessing
|
||||||
virtual void endPass() = 0;
|
virtual void postProcess() = 0;
|
||||||
|
/// Finalise frame
|
||||||
|
virtual void endFrame() = 0;
|
||||||
/// Swap displayed image
|
/// Swap displayed image
|
||||||
virtual void swapBuffer(Window &) = 0;
|
virtual void swapBuffer(Window &) = 0;
|
||||||
|
|
||||||
|
@ -78,7 +81,6 @@ public:
|
||||||
virtual void lookFrom(const Camera &) = 0;
|
virtual void lookFrom(const Camera &) = 0;
|
||||||
|
|
||||||
virtual void setClearColor(glm::vec4) = 0;
|
virtual void setClearColor(glm::vec4) = 0;
|
||||||
virtual void setCurvature(glm::vec4, float) = 0;
|
|
||||||
virtual void reloadShaders(const passOptions &) = 0;
|
virtual void reloadShaders(const passOptions &) = 0;
|
||||||
virtual void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) = 0;
|
virtual void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) = 0;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
std::unique_ptr<Texture> (*Texture::loadFunc)(const std::string&, const sampling&) = nullptr;
|
std::unique_ptr<Texture> (*Texture::loadFunc)(const std::string&, const sampling&) = nullptr;
|
||||||
|
std::unique_ptr<TextureCube> (*TextureCube::loadFunc)(const std::array<std::string, 6>&, const Texture::sampling &) = nullptr;
|
||||||
|
std::unique_ptr<TextureArray> (*TextureArray::loadFunc)(const std::vector<std::string>&, const Texture::sampling &) = nullptr;
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
|
@ -73,20 +73,24 @@ public:
|
||||||
};
|
};
|
||||||
struct requirement: properties {
|
struct requirement: properties {
|
||||||
requirement(const properties& props, Layout layout, Usage usage, Aspect aspect,
|
requirement(const properties& props, Layout layout, Usage usage, Aspect aspect,
|
||||||
int samples = 1, bool optimal = true): properties(props), layout(layout),
|
int samples = 1, uint32_t layers = 1, bool cube = false, bool optimal = true):
|
||||||
usage(usage), aspect(aspect), samples(samples), optimal(optimal)
|
properties(props), layout(layout), usage(usage), aspect(aspect), samples(samples),
|
||||||
|
layers(layers), cube(cube), optimal(optimal)
|
||||||
{
|
{
|
||||||
assert(samples > 0 && (std::ceil(std::log2(samples)) == std::floor(std::log2(samples))) && "Samples must be pow2");
|
assert(samples > 0 && (std::ceil(std::log2(samples)) == std::floor(std::log2(samples))) && "Samples must be pow2");
|
||||||
|
assert(!cube || layers == 6);
|
||||||
}
|
}
|
||||||
Layout layout;
|
Layout layout;
|
||||||
Usage usage;
|
Usage usage;
|
||||||
Aspect aspect;
|
Aspect aspect;
|
||||||
//NOTE: matches VkSampleCountFlagBits
|
//NOTE: matches VkSampleCountFlagBits
|
||||||
int samples;
|
int samples;
|
||||||
|
uint32_t layers;
|
||||||
|
bool cube;
|
||||||
bool optimal;
|
bool optimal;
|
||||||
|
|
||||||
static requirement Texture(const properties &props) {
|
static requirement Texture(const properties &props, uint32_t arraySize = 1, bool cube = false) {
|
||||||
return requirement(props, Layout::SHADER_READ_ONLY, Usage::SAMPLED, Aspect::COLOR); }
|
return requirement(props, Layout::SHADER_READ_ONLY, Usage::SAMPLED, Aspect::COLOR, 1, arraySize, cube); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::optional<properties> Read(const std::string&, std::vector<unsigned char>& data);
|
static std::optional<properties> Read(const std::string&, std::vector<unsigned char>& data);
|
||||||
|
@ -120,4 +124,36 @@ public:
|
||||||
protected:
|
protected:
|
||||||
static std::unique_ptr<Texture> (*loadFunc)(const std::string&, const sampling&);
|
static std::unique_ptr<Texture> (*loadFunc)(const std::string&, const sampling&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Const 6 dept image (single textureCube) with sampler
|
||||||
|
class TextureCube: public Image {
|
||||||
|
public:
|
||||||
|
/// Only supports dds files
|
||||||
|
/// DXT3(BC2) DXT5(BC3)
|
||||||
|
static _FORCE_INLINE_ std::unique_ptr<TextureCube> LoadFromFiles(const std::array<std::string, 6> &paths, const Texture::sampling &props) {
|
||||||
|
assert(loadFunc != nullptr && "Uninitialized renderer");
|
||||||
|
return loadFunc(paths, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::unique_ptr<TextureCube> (*loadFunc)(const std::array<std::string, 6>&, const Texture::sampling&);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Const image array (textureArray) with sampler
|
||||||
|
class TextureArray: public Image {
|
||||||
|
public:
|
||||||
|
/// Only supports dds files
|
||||||
|
/// DXT3(BC2) DXT5(BC3)
|
||||||
|
static _FORCE_INLINE_ std::unique_ptr<TextureArray> LoadFromFiles(const std::vector<std::string> &paths, const Texture::sampling &props) {
|
||||||
|
assert(loadFunc != nullptr && "Uninitialized renderer");
|
||||||
|
return loadFunc(paths, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t getSize() const { return size; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextureArray(uint32_t size): size(size) { }
|
||||||
|
uint32_t size;
|
||||||
|
static std::unique_ptr<TextureArray> (*loadFunc)(const std::vector<std::string>&, const Texture::sampling&);
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -115,11 +115,11 @@ void Renderer::beginFrame() {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<size_t(render::LodModel *const, glm::mat4)> Renderer::beginWorldPass() {
|
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Renderer::beginWorldPass() {
|
||||||
WorldPass->useIt();
|
WorldPass->useIt();
|
||||||
WorldPass->start(this);
|
WorldPass->start(this);
|
||||||
return [&](render::LodModel *const buf, glm::mat4 model) {
|
return [&](render::LodModel *const buf, glm::mat4 model, glm::vec4 sph, float curv) {
|
||||||
WorldPass->setup(this, model);
|
WorldPass->setup(model, sph, curv);
|
||||||
return dynamic_cast<LodModel *const>(buf)->draw();
|
return dynamic_cast<LodModel *const>(buf)->draw();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> Rend
|
||||||
EntityPass->useIt();
|
EntityPass->useIt();
|
||||||
EntityPass->start(this);
|
EntityPass->start(this);
|
||||||
return [&](render::Model *const buf, const std::vector<glm::mat4> &models) {
|
return [&](render::Model *const buf, const std::vector<glm::mat4> &models) {
|
||||||
EntityPass->setup(this, models);
|
EntityPass->setup(models);
|
||||||
return dynamic_cast<Model *const>(buf)->drawInstanced(models.size());
|
return dynamic_cast<Model *const>(buf)->drawInstanced(models.size());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -139,11 +139,12 @@ size_t Renderer::drawIndicatorCube(glm::mat4 model) {
|
||||||
return IndicatorCubeBuffer.draw();
|
return IndicatorCubeBuffer.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::endPass() {
|
void Renderer::postProcess() {
|
||||||
if(SkyEnable) {
|
if(SkyEnable) {
|
||||||
SkyPass->draw(this);
|
SkyPass->draw(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Renderer::endFrame() { }
|
||||||
|
|
||||||
void Renderer::swapBuffer(Window& w) {
|
void Renderer::swapBuffer(Window& w) {
|
||||||
TracyGpuZone("Swap");
|
TracyGpuZone("Swap");
|
||||||
|
@ -188,7 +189,3 @@ void Renderer::setClearColor(glm::vec4 c) {
|
||||||
FogColor = c;
|
FogColor = c;
|
||||||
glClearColor(c.r, c.g, c.b, c.a);
|
glClearColor(c.r, c.g, c.b, c.a);
|
||||||
}
|
}
|
||||||
void Renderer::setCurvature(glm::vec4 sp, float c) {
|
|
||||||
SphereProj = sp;
|
|
||||||
Curvature = c;
|
|
||||||
}
|
|
|
@ -41,20 +41,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void beginFrame() override;
|
void beginFrame() override;
|
||||||
std::function<size_t(render::LodModel *const, glm::mat4)> beginWorldPass() override;
|
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass() override;
|
||||||
std::function<size_t(render::Model *const, const std::vector<glm::mat4>&)> beginEntityPass() override;
|
std::function<size_t(render::Model *const, const std::vector<glm::mat4>&)> beginEntityPass() override;
|
||||||
size_t drawIndicatorCube(glm::mat4 model) override;
|
size_t drawIndicatorCube(glm::mat4 model) override;
|
||||||
void endPass() override;
|
void postProcess() override;
|
||||||
|
void endFrame() override;
|
||||||
void swapBuffer(Window&) override;
|
void swapBuffer(Window&) override;
|
||||||
|
|
||||||
void setClearColor(glm::vec4) override;
|
void setClearColor(glm::vec4) override;
|
||||||
void setCurvature(glm::vec4, float) override;
|
|
||||||
glm::vec4 getSphereProj() const {
|
|
||||||
return SphereProj;
|
|
||||||
}
|
|
||||||
float getCurvature() const {
|
|
||||||
return Curvature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply camera matrices
|
/// Apply camera matrices
|
||||||
void lookFrom(const Camera&) override;
|
void lookFrom(const Camera&) override;
|
||||||
|
@ -84,12 +78,6 @@ private:
|
||||||
GLuint HOSAtlas;
|
GLuint HOSAtlas;
|
||||||
GLuint Skybox;
|
GLuint Skybox;
|
||||||
|
|
||||||
/// Sphere bending
|
|
||||||
/// offset.xyz radius.w
|
|
||||||
glm::vec4 SphereProj;
|
|
||||||
/// Ratio between spherical and cartesian
|
|
||||||
float Curvature;
|
|
||||||
|
|
||||||
/// Draw skybox
|
/// Draw skybox
|
||||||
bool SkyEnable;
|
bool SkyEnable;
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ EntityProgram::EntityProgram(const EntityProgram::options &opts) : VoxelProgram(
|
||||||
}
|
}
|
||||||
EntityProgram::~EntityProgram() { }
|
EntityProgram::~EntityProgram() { }
|
||||||
|
|
||||||
void EntityProgram::setup(render::gl::Renderer *renderer, const std::vector<glm::mat4>& modelsMatrices) {
|
void EntityProgram::setup(const std::vector<glm::mat4>& modelsMatrices) {
|
||||||
setModels(&modelsMatrices[0][0][0], modelsMatrices.size());
|
setModels(&modelsMatrices[0][0][0], modelsMatrices.size());
|
||||||
VoxelProgram::setup(renderer);
|
VoxelProgram::setup(glm::vec4(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityProgram::setModels(const GLfloat *matrices, size_t count) {
|
void EntityProgram::setModels(const GLfloat *matrices, size_t count) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace pass {
|
||||||
|
|
||||||
static constexpr auto LOCATION = 6;
|
static constexpr auto LOCATION = 6;
|
||||||
|
|
||||||
void setup(render::gl::Renderer *, const std::vector<glm::mat4> &modelsMatrices);
|
void setup(const std::vector<glm::mat4> &modelsMatrices);
|
||||||
void disable();
|
void disable();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -62,9 +62,9 @@ void VoxelProgram::start(render::gl::Renderer *renderer) {
|
||||||
setView(&renderer->getViewMatrix()[0][0]);
|
setView(&renderer->getViewMatrix()[0][0]);
|
||||||
setProj(&renderer->getProjectionMatrix()[0][0]);
|
setProj(&renderer->getProjectionMatrix()[0][0]);
|
||||||
}
|
}
|
||||||
void VoxelProgram::setup(render::gl::Renderer *renderer) {
|
void VoxelProgram::setup(glm::vec4 sphereProj, float curvature) {
|
||||||
setSphereProj(&renderer->getSphereProj()[0]);
|
setSphereProj(&sphereProj[0]);
|
||||||
setCurvature(renderer->getCurvature());
|
setCurvature(curvature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelProgram::setProj(const GLfloat *matrix) {
|
void VoxelProgram::setProj(const GLfloat *matrix) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace pass {
|
||||||
void start(render::gl::Renderer *);
|
void start(render::gl::Renderer *);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setup(render::gl::Renderer *);
|
void setup(glm::vec4 sphereProj, float curvature);
|
||||||
|
|
||||||
std::string getName() const override;
|
std::string getName() const override;
|
||||||
void setView(const GLfloat *matrix);
|
void setView(const GLfloat *matrix);
|
||||||
|
|
|
@ -11,9 +11,9 @@ WorldProgram::WorldProgram(const WorldProgram::options& opts): VoxelProgram(opts
|
||||||
|
|
||||||
WorldProgram::~WorldProgram() { }
|
WorldProgram::~WorldProgram() { }
|
||||||
|
|
||||||
void WorldProgram::setup(render::gl::Renderer *renderer, glm::mat4 modelMatrix) {
|
void WorldProgram::setup(glm::mat4 modelMatrix, glm::vec4 sphereProj, float curvature) {
|
||||||
setModel(&modelMatrix[0][0]);
|
setModel(&modelMatrix[0][0]);
|
||||||
VoxelProgram::setup(renderer);
|
VoxelProgram::setup(sphereProj, curvature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldProgram::setModel(const GLfloat *matrix) {
|
void WorldProgram::setModel(const GLfloat *matrix) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace pass {
|
||||||
WorldProgram(const options &opts);
|
WorldProgram(const options &opts);
|
||||||
~WorldProgram();
|
~WorldProgram();
|
||||||
|
|
||||||
void setup(render::gl::Renderer *, glm::mat4 modelMatrix);
|
void setup(glm::mat4 modelMatrix, glm::vec4 sphereProj, float curvature);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setModel(const GLfloat *matrix);
|
void setModel(const GLfloat *matrix);
|
||||||
|
|
|
@ -195,7 +195,7 @@ void Allocator::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) {
|
||||||
|
|
||||||
submitCmd(transferBuffer, transferQueue);
|
submitCmd(transferBuffer, transferQueue);
|
||||||
}
|
}
|
||||||
void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels) {
|
void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, uint32_t arrayLayers) {
|
||||||
beginCmd(graphicsBuffer);
|
beginCmd(graphicsBuffer);
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{};
|
VkImageMemoryBarrier barrier{};
|
||||||
|
@ -210,7 +210,7 @@ void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLay
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
barrier.subresourceRange.levelCount = mipLevels;
|
barrier.subresourceRange.levelCount = mipLevels;
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.layerCount = 1;
|
barrier.subresourceRange.layerCount = arrayLayers;
|
||||||
|
|
||||||
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
|
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
@ -257,7 +257,7 @@ void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLay
|
||||||
|
|
||||||
submitCmd(graphicsBuffer, graphicsQueue);
|
submitCmd(graphicsBuffer, graphicsQueue);
|
||||||
}
|
}
|
||||||
void Allocator::copyBufferToImage(VkBuffer src, VkImage dest, uint32_t width, uint32_t height, uint32_t mipLevels) {
|
void Allocator::copyBufferToImage(VkBuffer src, VkImage dest, uint32_t width, uint32_t height, uint32_t mipLevels, uint32_t arrayLayer) {
|
||||||
|
|
||||||
beginCmd(transferBuffer);
|
beginCmd(transferBuffer);
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ void Allocator::copyBufferToImage(VkBuffer src, VkImage dest, uint32_t width, ui
|
||||||
for (size_t i = 0; i < mipLevels; i++) {
|
for (size_t i = 0; i < mipLevels; i++) {
|
||||||
regions[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
regions[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
regions[i].imageSubresource.mipLevel = i;
|
regions[i].imageSubresource.mipLevel = i;
|
||||||
regions[i].imageSubresource.baseArrayLayer = 0;
|
regions[i].imageSubresource.baseArrayLayer = arrayLayer;
|
||||||
regions[i].imageSubresource.layerCount = 1;
|
regions[i].imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
regions[i].imageOffset = {0, 0, 0};
|
regions[i].imageOffset = {0, 0, 0};
|
||||||
|
|
|
@ -37,8 +37,8 @@ public:
|
||||||
bool deallocate(const memory::area&);
|
bool deallocate(const memory::area&);
|
||||||
|
|
||||||
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size);
|
||||||
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels);
|
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, uint32_t arrayLayers);
|
||||||
void copyBufferToImage(VkBuffer src, VkImage dst, uint32_t width, uint32_t height, uint32_t mipLevels = 1);
|
void copyBufferToImage(VkBuffer src, VkImage dst, uint32_t width, uint32_t height, uint32_t mipLevels = 1, uint32_t arrayLayer = 0);
|
||||||
|
|
||||||
void setTracyZone(const char* name);
|
void setTracyZone(const char* name);
|
||||||
|
|
||||||
|
|
|
@ -16,24 +16,38 @@ CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, co
|
||||||
VkCommandPoolCreateInfo poolInfo{};
|
VkCommandPoolCreateInfo poolInfo{};
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
|
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
|
||||||
poolInfo.flags = 0;
|
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
|
||||||
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
|
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create graphics pool!");
|
FATAL("Failed to create graphics pool!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Vertex buffers (const)
|
|
||||||
modelBuffer = ShortIndexedVertexBuffer::Create(buffer::vk::vertices, buffer::vk::indices);
|
modelBuffer = ShortIndexedVertexBuffer::Create(buffer::vk::vertices, buffer::vk::indices);
|
||||||
if (!modelBuffer) {
|
if (!modelBuffer) {
|
||||||
FATAL("Cannot create vertex buffer");
|
FATAL("Cannot create vertex buffer");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{ // Texture sampler (const)
|
sampleTexture = Texture::LoadFromFile(TEXTURES_DIR + opt.textures + "/terrain/Mapl.dds", {true, true, Texture::Wrap::MIRRORED_REPEAT, opt.anisotropy});
|
||||||
sampleTexture = Texture::LoadFromFile(TEXTURES_DIR "1024-realistic/terrain/Mapl.dds", {true, true, Texture::Wrap::MIRRORED_REPEAT, opt.anisotropy});
|
if (!sampleTexture) {
|
||||||
if (!sampleTexture) {
|
FATAL("Failed to create texture sampler!");
|
||||||
FATAL("Failed to create texture sampler!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skyCubeBuffer = Shape::Create({
|
||||||
|
{-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f},
|
||||||
|
{-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f},
|
||||||
|
{ 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f},
|
||||||
|
{-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f},
|
||||||
|
{-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f},
|
||||||
|
{-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}
|
||||||
|
});
|
||||||
|
if (!skyCubeBuffer) {
|
||||||
|
FATAL("Failed to create vertex buffer!");
|
||||||
|
}
|
||||||
|
skyboxTexture = TextureCube::LoadFromFiles(TEXTURES_DIR + opt.textures + "/sky/Space_tray.cube", {});
|
||||||
|
if (!skyboxTexture) {
|
||||||
|
FATAL("Failed to create texture sampler!");
|
||||||
|
}
|
||||||
|
|
||||||
colorFormat = info.getSurfaceFormat().format;
|
colorFormat = info.getSurfaceFormat().format;
|
||||||
colorSamples = info.samples;
|
colorSamples = info.samples;
|
||||||
LOG_D("Samples: " << colorSamples);
|
LOG_D("Samples: " << colorSamples);
|
||||||
|
@ -46,12 +60,12 @@ CommandCenter::~CommandCenter() {
|
||||||
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
vkDestroyCommandPool(device, graphicsPool, ALLOC);
|
||||||
}
|
}
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent, const renderOptions& opt) {
|
void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeline& pipe, VkExtent2D extent) {
|
||||||
assert(freed);
|
assert(freed);
|
||||||
|
|
||||||
if (colorSamples > 1) {
|
if (colorSamples > 1) {
|
||||||
colorbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)colorFormat},
|
colorbuffer = Image::Create(Image::requirement({{extent.height, extent.width}, 1, (Image::Format)colorFormat},
|
||||||
Image::Layout::COLOR_ATTACHMENT, Image::Usage::COLOR_ATTACHMENT | Image::Usage::TRANSIENT_ATTACHMENT,
|
Image::Layout::COLOR_ATTACHMENT, Image::Usage::COLOR_ATTACHMENT | Image::Usage::TRANSIENT_ATTACHMENT, // NOTE: VulkanTutorial#118
|
||||||
Image::Aspect::COLOR, colorSamples));
|
Image::Aspect::COLOR, colorSamples));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,16 +98,14 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Uniform buffers
|
{ // Uniform buffers
|
||||||
VkDeviceSize bufferSize = sizeof(buffer::vk::UniformBufferObject);
|
|
||||||
|
|
||||||
std::vector<Buffer::requirement> requirements;
|
std::vector<Buffer::requirement> requirements;
|
||||||
requirements.resize(framebuffers.size(), Buffer::requirement(bufferSize, Buffer::Usage::UNIFORM));
|
requirements.resize(framebuffers.size(), Buffer::requirement(sizeof(buffer::vk::UniformBufferObject), Buffer::Usage::UNIFORM));
|
||||||
uniformBuffers.allocate(requirements, true);
|
uniformBuffers.allocate(requirements, true);
|
||||||
if (!uniformBuffers) {
|
if (!uniformBuffers) {
|
||||||
FATAL("Failed to allocate UBO");
|
FATAL("Failed to allocate UBO");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Descriptor pool
|
{ // Voxel Descriptor pool
|
||||||
std::array<VkDescriptorPoolSize, 2> poolSizes{};
|
std::array<VkDescriptorPoolSize, 2> poolSizes{};
|
||||||
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
poolSizes[0].descriptorCount = framebuffers.size();
|
poolSizes[0].descriptorCount = framebuffers.size();
|
||||||
|
@ -107,24 +119,37 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
poolInfo.maxSets = framebuffers.size();
|
poolInfo.maxSets = framebuffers.size();
|
||||||
poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
|
poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
|
||||||
|
|
||||||
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
|
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &voxelDescriptorPool) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create descriptor pool!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &skyDescriptorPool) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create descriptor pool!");
|
FATAL("Failed to create descriptor pool!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Descriptor sets
|
{ // Descriptor sets
|
||||||
std::vector<VkDescriptorSetLayout> layouts(framebuffers.size(), pipe.getDescriptorSet());
|
std::vector<VkDescriptorSetLayout> voxLayouts(framebuffers.size(), pipe.getVoxelDescriptorSet());
|
||||||
VkDescriptorSetAllocateInfo allocInfo{};
|
VkDescriptorSetAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
allocInfo.descriptorPool = descriptorPool;
|
allocInfo.descriptorPool = voxelDescriptorPool;
|
||||||
allocInfo.descriptorSetCount = framebuffers.size();
|
allocInfo.descriptorSetCount = framebuffers.size();
|
||||||
allocInfo.pSetLayouts = layouts.data();
|
allocInfo.pSetLayouts = voxLayouts.data();
|
||||||
|
|
||||||
descriptorSets.resize(framebuffers.size());
|
voxelDescriptorSets.resize(framebuffers.size());
|
||||||
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
|
if (vkAllocateDescriptorSets(device, &allocInfo, voxelDescriptorSets.data()) != VK_SUCCESS) {
|
||||||
FATAL("Failed to allocate descriptor sets!");
|
FATAL("Failed to allocate descriptor sets!");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < descriptorSets.size(); i++) {
|
std::vector<VkDescriptorSetLayout> skyLayouts(framebuffers.size(), pipe.getSkyDescriptorSet());
|
||||||
|
allocInfo.descriptorPool = skyDescriptorPool;
|
||||||
|
allocInfo.pSetLayouts = skyLayouts.data();
|
||||||
|
|
||||||
|
skyDescriptorSets.resize(framebuffers.size());
|
||||||
|
if (vkAllocateDescriptorSets(device, &allocInfo, skyDescriptorSets.data()) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to allocate descriptor sets!");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < voxelDescriptorSets.size(); i++) {
|
||||||
VkDescriptorBufferInfo bufferInfo{};
|
VkDescriptorBufferInfo bufferInfo{};
|
||||||
bufferInfo.buffer = uniformBuffers.at(i);
|
bufferInfo.buffer = uniformBuffers.at(i);
|
||||||
bufferInfo.offset = 0;
|
bufferInfo.offset = 0;
|
||||||
|
@ -132,7 +157,7 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
|
|
||||||
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
|
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
|
||||||
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptorWrites[0].dstSet = descriptorSets[i];
|
descriptorWrites[0].dstSet = voxelDescriptorSets[i];
|
||||||
descriptorWrites[0].dstBinding = 0;
|
descriptorWrites[0].dstBinding = 0;
|
||||||
descriptorWrites[0].dstArrayElement = 0;
|
descriptorWrites[0].dstArrayElement = 0;
|
||||||
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
@ -140,7 +165,7 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
descriptorWrites[0].pBufferInfo = &bufferInfo;
|
descriptorWrites[0].pBufferInfo = &bufferInfo;
|
||||||
|
|
||||||
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptorWrites[1].dstSet = descriptorSets[i];
|
descriptorWrites[1].dstSet = voxelDescriptorSets[i];
|
||||||
descriptorWrites[1].dstBinding = 1;
|
descriptorWrites[1].dstBinding = 1;
|
||||||
descriptorWrites[1].dstArrayElement = 0;
|
descriptorWrites[1].dstArrayElement = 0;
|
||||||
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
@ -148,9 +173,13 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
descriptorWrites[1].pImageInfo = &sampleTexture->getDescriptor();
|
descriptorWrites[1].pImageInfo = &sampleTexture->getDescriptor();
|
||||||
|
|
||||||
vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
||||||
|
|
||||||
|
descriptorWrites[0].dstSet = skyDescriptorSets[i];
|
||||||
|
descriptorWrites[1].dstSet = skyDescriptorSets[i];
|
||||||
|
descriptorWrites[1].pImageInfo = &skyboxTexture->getDescriptor();
|
||||||
|
vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
graphicsBuffers.resize(framebuffers.size());
|
graphicsBuffers.resize(framebuffers.size());
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
|
@ -164,44 +193,6 @@ void CommandCenter::allocate(const std::vector<VkImageView>& views, const Pipeli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < graphicsBuffers.size(); 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) {
|
|
||||||
FATAL("Failed to begin recording command buffer!");
|
|
||||||
}
|
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
||||||
renderPassInfo.renderPass = pipe.getRenderPass();
|
|
||||||
renderPassInfo.framebuffer = framebuffers[i];
|
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
|
||||||
renderPassInfo.renderArea.extent = extent;
|
|
||||||
|
|
||||||
std::array<VkClearValue, 2> clearValues{};
|
|
||||||
clearValues[0].color = {opt.clear_color.x, opt.clear_color.y, opt.clear_color.z, opt.clear_color.a};
|
|
||||||
clearValues[1].depthStencil = {1.0f, 0};
|
|
||||||
renderPassInfo.clearValueCount = clearValues.size();
|
|
||||||
renderPassInfo.pClearValues = clearValues.data();
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass(graphicsBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
|
||||||
vkCmdBindPipeline(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getPipeline());
|
|
||||||
VkBuffer vertexBuffers[] = {modelBuffer->getVertex()};
|
|
||||||
VkDeviceSize offsets[] = {0};
|
|
||||||
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
|
|
||||||
vkCmdBindIndexBuffer(graphicsBuffers[i], modelBuffer->getIndex(), 0, VK_INDEX_TYPE_UINT16);
|
|
||||||
vkCmdBindDescriptorSets(graphicsBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.getLayout(), 0, 1, &descriptorSets[i], 0, nullptr);
|
|
||||||
vkCmdDrawIndexed(graphicsBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
|
|
||||||
vkCmdEndRenderPass(graphicsBuffers[i]);
|
|
||||||
|
|
||||||
if (vkEndCommandBuffer(graphicsBuffers[i]) != VK_SUCCESS) {
|
|
||||||
FATAL("Failed to record graphics buffer!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proj = glm::perspectiveZO(glm::radians(45.0f), extent.width / (float) extent.height, 0.1f, 10.0f);
|
proj = glm::perspectiveZO(glm::radians(45.0f), extent.width / (float) extent.height, 0.1f, 10.0f);
|
||||||
proj[1][1] *= -1;
|
proj[1][1] *= -1;
|
||||||
|
|
||||||
|
@ -211,13 +202,14 @@ void CommandCenter::free() {
|
||||||
assert(!freed);
|
assert(!freed);
|
||||||
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
|
vkFreeCommandBuffers(device, graphicsPool, static_cast<uint32_t>(graphicsBuffers.size()), graphicsBuffers.data());
|
||||||
|
|
||||||
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
|
vkDestroyDescriptorPool(device, voxelDescriptorPool, ALLOC);
|
||||||
|
vkDestroyDescriptorPool(device, skyDescriptorPool, ALLOC);
|
||||||
|
|
||||||
colorbuffer.reset();
|
colorbuffer.reset();
|
||||||
depthbuffer.reset();
|
depthbuffer.reset();
|
||||||
|
|
||||||
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], ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
freed = true;
|
freed = true;
|
||||||
|
@ -226,22 +218,79 @@ void CommandCenter::free() {
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
void CommandCenter::updateUBO(uint32_t idx) {
|
void CommandCenter::startRecording(uint32_t idx, VkRenderPass renderPass, VkExtent2D extent, const glm::vec4& clear_color, glm::mat4 view, glm::mat4 proj) {
|
||||||
|
buffer::vk::UniformBufferObject ubo{};
|
||||||
|
ubo.view = view;
|
||||||
|
ubo.proj = proj;
|
||||||
|
uniformBuffers.write(idx, data_view(&ubo, sizeof(ubo)));
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
//TODO: reuse
|
||||||
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
|
if (vkBeginCommandBuffer(graphicsBuffers[idx], &beginInfo) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to begin recording command buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkRenderPassBeginInfo renderPassInfo{};
|
||||||
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
renderPassInfo.renderPass = renderPass;
|
||||||
|
renderPassInfo.framebuffer = framebuffers[idx];
|
||||||
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
|
renderPassInfo.renderArea.extent = extent;
|
||||||
|
|
||||||
|
std::array<VkClearValue, 2> clearValues{};
|
||||||
|
clearValues[0].color = {clear_color.x, clear_color.y, clear_color.z, clear_color.a};
|
||||||
|
clearValues[1].depthStencil = {1.0f, 0};
|
||||||
|
renderPassInfo.clearValueCount = clearValues.size();
|
||||||
|
renderPassInfo.pClearValues = clearValues.data();
|
||||||
|
|
||||||
|
vkCmdBeginRenderPass(graphicsBuffers[idx], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandCenter::startWorldPass(uint32_t idx, const Subpass &worldPass) {
|
||||||
|
vkCmdBindPipeline(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, worldPass.pipeline);
|
||||||
|
vkCmdBindDescriptorSets(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, worldPass.layout, 0, 1, &voxelDescriptorSets[idx], 0, nullptr);
|
||||||
|
|
||||||
static auto startTime = std::chrono::high_resolution_clock::now();
|
static auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||||
buffer::vk::UniformBufferObject ubo{};
|
buffer::vk::ModelPush push{};
|
||||||
time = 0.1;
|
push.model = glm::translate(glm::mat4(1.0f), glm::vec3(98.0f, -2.f, -2.f));
|
||||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
push.model = glm::rotate(push.model, time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
vkCmdPushConstants(graphicsBuffers[idx], worldPass.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push), &push);
|
||||||
ubo.proj = proj;
|
}
|
||||||
uniformBuffers.write(idx, data_view(&ubo, sizeof(ubo)));
|
void CommandCenter::recordModel(uint32_t i) {
|
||||||
|
VkBuffer vertexBuffers[] = {modelBuffer->getVertex()};
|
||||||
|
VkDeviceSize offsets[] = {0};
|
||||||
|
vkCmdBindVertexBuffers(graphicsBuffers[i], 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdBindIndexBuffer(graphicsBuffers[i], modelBuffer->getIndex(), 0, VK_INDEX_TYPE_UINT16);
|
||||||
|
vkCmdDrawIndexed(graphicsBuffers[i], static_cast<uint32_t>(buffer::vk::indices.size()), 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
void CommandCenter::startEntityPass(uint32_t) { }
|
||||||
|
void CommandCenter::recordPostprocess(uint32_t idx, const Subpass& skyPass, bool skybox, glm::mat4, glm::mat4) {
|
||||||
|
vkCmdNextSubpass(graphicsBuffers[idx], VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
if (skybox) {
|
||||||
|
vkCmdBindPipeline(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, skyPass.pipeline);
|
||||||
|
vkCmdBindDescriptorSets(graphicsBuffers[idx], VK_PIPELINE_BIND_POINT_GRAPHICS, skyPass.layout, 0, 1, &skyDescriptorSets[idx], 0, nullptr);
|
||||||
|
VkBuffer vertexBuffers[] = {skyCubeBuffer->getRef()};
|
||||||
|
VkDeviceSize offsets[] = {0};
|
||||||
|
vkCmdBindVertexBuffers(graphicsBuffers[idx], 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdDraw(graphicsBuffers[idx], skyCubeBuffer->size, 1, 0, 0);
|
||||||
|
}
|
||||||
|
vkCmdEndRenderPass(graphicsBuffers[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
void CommandCenter::submitGraphics(uint32_t idx, VkSemaphore waitSemaphore, VkSemaphore signalSemaphore, VkFence submittedFence) {
|
||||||
assert(!freed);
|
assert(!freed);
|
||||||
|
|
||||||
|
if (vkEndCommandBuffer(graphicsBuffers[idx]) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to record graphics buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{};
|
VkSubmitInfo submitInfo{};
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
|
||||||
|
|
|
@ -5,20 +5,27 @@
|
||||||
#include <glm/mat4x4.hpp>
|
#include <glm/mat4x4.hpp>
|
||||||
#include "api/Buffers.hpp"
|
#include "api/Buffers.hpp"
|
||||||
#include "api/Images.hpp"
|
#include "api/Images.hpp"
|
||||||
|
#include "api/Models.hpp"
|
||||||
|
|
||||||
namespace render::vk {
|
namespace render::vk {
|
||||||
class SwapChain;
|
class SwapChain;
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
|
struct Subpass;
|
||||||
|
|
||||||
class CommandCenter final {
|
class CommandCenter final {
|
||||||
public:
|
public:
|
||||||
CommandCenter(VkDevice, const PhysicalDeviceInfo&, const renderOptions&);
|
CommandCenter(VkDevice, const PhysicalDeviceInfo&, const renderOptions&);
|
||||||
~CommandCenter();
|
~CommandCenter();
|
||||||
|
|
||||||
void updateUBO(uint32_t idx);
|
void startRecording(uint32_t idx, VkRenderPass, VkExtent2D, const glm::vec4& clear, glm::mat4 view, glm::mat4 proj);
|
||||||
|
void startWorldPass(uint32_t idx, const Subpass&);
|
||||||
|
void recordModel(uint32_t idx);
|
||||||
|
void startEntityPass(uint32_t idx);
|
||||||
|
//void recordModel(uint32_t idx);
|
||||||
|
void recordPostprocess(uint32_t idx, const Subpass&, bool skybox, glm::mat4 view, glm::mat4 proj);
|
||||||
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
void submitGraphics(uint32_t, VkSemaphore, VkSemaphore, VkFence);
|
||||||
|
|
||||||
void allocate(const std::vector<VkImageView>&, const Pipeline&, VkExtent2D, const renderOptions&);
|
void allocate(const std::vector<VkImageView>&, const Pipeline&, VkExtent2D);
|
||||||
void free();
|
void free();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -36,15 +43,19 @@ private:
|
||||||
VkCommandPool graphicsPool;
|
VkCommandPool graphicsPool;
|
||||||
std::vector<VkCommandBuffer> graphicsBuffers;
|
std::vector<VkCommandBuffer> graphicsBuffers;
|
||||||
|
|
||||||
VkDescriptorPool descriptorPool;
|
BufferGroup uniformBuffers;
|
||||||
std::vector<VkDescriptorSet> descriptorSets;
|
|
||||||
|
|
||||||
|
VkDescriptorPool voxelDescriptorPool;
|
||||||
|
std::vector<VkDescriptorSet> voxelDescriptorSets;
|
||||||
|
std::unique_ptr<Texture> sampleTexture;
|
||||||
std::unique_ptr<ShortIndexedVertexBuffer> modelBuffer;
|
std::unique_ptr<ShortIndexedVertexBuffer> modelBuffer;
|
||||||
|
|
||||||
std::unique_ptr<Texture> sampleTexture;
|
VkDescriptorPool skyDescriptorPool;
|
||||||
|
std::vector<VkDescriptorSet> skyDescriptorSets;
|
||||||
|
std::unique_ptr<TextureCube> skyboxTexture;
|
||||||
|
std::unique_ptr<Shape> skyCubeBuffer;
|
||||||
|
|
||||||
glm::mat4 proj;
|
glm::mat4 proj;
|
||||||
BufferGroup uniformBuffers;
|
|
||||||
|
|
||||||
bool freed = true;
|
bool freed = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../../../core/data/file.hpp"
|
#include "../../../core/data/file.hpp"
|
||||||
#include "../Renderer.hpp"
|
#include "../Renderer.hpp"
|
||||||
#include "buffer/VertexData.hpp"
|
#include "buffer/VertexData.hpp"
|
||||||
|
#include "api/Models.hpp"
|
||||||
|
|
||||||
#define CONTENT_DIR "content/"
|
#define CONTENT_DIR "content/"
|
||||||
#define SHADER_DIR CONTENT_DIR "shaders/"
|
#define SHADER_DIR CONTENT_DIR "shaders/"
|
||||||
|
@ -58,24 +59,41 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
colorAttachmentResolveRef.attachment = 2;
|
colorAttachmentResolveRef.attachment = 2;
|
||||||
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
//TODO: subpasses (world, entities, colors, sky, ui)
|
VkSubpassDescription colorDepthSubpass{};
|
||||||
|
colorDepthSubpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
VkSubpassDescription subpass{};
|
colorDepthSubpass.colorAttachmentCount = 1;
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
colorDepthSubpass.pColorAttachments = &colorAttachmentRef;
|
||||||
subpass.colorAttachmentCount = 1;
|
colorDepthSubpass.pDepthStencilAttachment = &depthAttachmentRef;
|
||||||
subpass.pColorAttachments = &colorAttachmentRef;
|
|
||||||
subpass.pDepthStencilAttachment = &depthAttachmentRef;
|
|
||||||
if (hasSamples) {
|
if (hasSamples) {
|
||||||
subpass.pResolveAttachments = &colorAttachmentResolveRef;
|
colorDepthSubpass.pResolveAttachments = &colorAttachmentResolveRef;
|
||||||
}
|
}
|
||||||
|
std::array<VkSubpassDescription, 2> subpasses = {colorDepthSubpass, colorDepthSubpass};
|
||||||
|
|
||||||
VkSubpassDependency dependency{};
|
std::array<VkSubpassDependency, 3> dependencies{};
|
||||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
dependency.dstSubpass = 0;
|
dependencies[0].dstSubpass = 0;
|
||||||
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
dependency.srcAccessMask = 0;
|
dependencies[0].srcAccessMask = 0;
|
||||||
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
dependencies[0].dependencyFlags = 0;
|
||||||
|
|
||||||
|
dependencies[1].srcSubpass = 0;
|
||||||
|
dependencies[1].dstSubpass = 1;
|
||||||
|
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||||
|
|
||||||
|
dependencies[2].srcSubpass = 0;
|
||||||
|
dependencies[2].dstSubpass = 1;
|
||||||
|
dependencies[2].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
dependencies[2].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
dependencies[2].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
dependencies[2].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
dependencies[2].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
||||||
|
//FIXME: probably needs depth dependency and/or 1->external
|
||||||
|
|
||||||
VkRenderPassCreateInfo renderPassInfo{};
|
VkRenderPassCreateInfo renderPassInfo{};
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
@ -85,16 +103,16 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
}
|
}
|
||||||
renderPassInfo.attachmentCount = attachments.size();
|
renderPassInfo.attachmentCount = attachments.size();
|
||||||
renderPassInfo.pAttachments = attachments.data();
|
renderPassInfo.pAttachments = attachments.data();
|
||||||
renderPassInfo.subpassCount = 1;
|
renderPassInfo.subpassCount = subpasses.size();
|
||||||
renderPassInfo.pSubpasses = &subpass;
|
renderPassInfo.pSubpasses = subpasses.data();
|
||||||
renderPassInfo.dependencyCount = 1;
|
renderPassInfo.dependencyCount = dependencies.size();
|
||||||
renderPassInfo.pDependencies = &dependency;
|
renderPassInfo.pDependencies = dependencies.data();
|
||||||
|
|
||||||
if (vkCreateRenderPass(device, &renderPassInfo, ALLOC, &renderPass) != VK_SUCCESS) {
|
if (vkCreateRenderPass(device, &renderPassInfo, ALLOC, &renderPass) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create render pass!");
|
FATAL("Failed to create render pass!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{ // Voxel descriptor
|
||||||
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
|
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
|
||||||
samplerLayoutBinding.binding = 1;
|
samplerLayoutBinding.binding = 1;
|
||||||
samplerLayoutBinding.descriptorCount = 1;
|
samplerLayoutBinding.descriptorCount = 1;
|
||||||
|
@ -108,61 +126,172 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
layoutInfo.bindingCount = bindings.size();
|
layoutInfo.bindingCount = bindings.size();
|
||||||
layoutInfo.pBindings = bindings.data();
|
layoutInfo.pBindings = bindings.data();
|
||||||
|
|
||||||
if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &descriptorSetLayout) != VK_SUCCESS) {
|
if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &voxelDescriptorSet) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create descriptor set layout!");
|
FATAL("Failed to create descriptor set layout!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{ // Sky descriptor
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
samplerLayoutBinding.binding = 1;
|
||||||
pipelineLayoutInfo.setLayoutCount = 1;
|
samplerLayoutBinding.descriptorCount = 1;
|
||||||
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
|
samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 0;
|
samplerLayoutBinding.pImmutableSamplers = nullptr;
|
||||||
pipelineLayoutInfo.pPushConstantRanges = nullptr;
|
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, ALLOC, &pipelineLayout) != VK_SUCCESS) {
|
std::vector<VkDescriptorSetLayoutBinding> bindings = {buffer::vk::UniformBufferObject::getLayoutBinding(), samplerLayoutBinding};
|
||||||
FATAL("Failed to create pipeline layout!");
|
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||||
|
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
|
layoutInfo.bindingCount = bindings.size();
|
||||||
|
layoutInfo.pBindings = bindings.data();
|
||||||
|
|
||||||
|
if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &skyDescriptorSet) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create descriptor set layout!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // Pipeline
|
// Common pipeline settings
|
||||||
{ // Modules
|
auto setShaders = [&](Subpass &pass, const std::string &shaderName) -> std::vector<VkPipelineShaderStageCreateInfo> {
|
||||||
data::file_content vsFile({SHADER_DIR "Tris.vs.spv"});
|
auto createShaderModule = [&](const data::file_content &code) {
|
||||||
data::file_content fsFile({SHADER_DIR "Tris.fs.spv"});
|
VkShaderModuleCreateInfo createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
auto createShaderModule = [&](const data::file_content &code) {
|
createInfo.codeSize = code.size();
|
||||||
VkShaderModuleCreateInfo createInfo{};
|
createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
||||||
createInfo.codeSize = code.size();
|
|
||||||
createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
|
|
||||||
|
|
||||||
VkShaderModule shaderModule;
|
|
||||||
if (vkCreateShaderModule(device, &createInfo, ALLOC, &shaderModule) != VK_SUCCESS) {
|
|
||||||
FATAL("Failed to create shader module!");
|
|
||||||
}
|
|
||||||
return shaderModule;
|
|
||||||
};
|
|
||||||
|
|
||||||
vsShader = createShaderModule(vsFile);
|
|
||||||
fsShader = createShaderModule(fsFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
VkShaderModule shaderModule;
|
||||||
|
if (vkCreateShaderModule(device, &createInfo, ALLOC, &shaderModule) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create shader module!");
|
||||||
|
}
|
||||||
|
return shaderModule;
|
||||||
|
};
|
||||||
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
|
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
|
||||||
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
vertShaderStageInfo.module = vsShader;
|
data::file_content vsFile({SHADER_DIR + shaderName + ".vs.spv"});
|
||||||
|
vertShaderStageInfo.module = pass.vsShader = createShaderModule(vsFile);
|
||||||
vertShaderStageInfo.pName = "main";
|
vertShaderStageInfo.pName = "main";
|
||||||
vertShaderStageInfo.pSpecializationInfo = nullptr; //TODO: pass constants
|
vertShaderStageInfo.pSpecializationInfo = nullptr; //TODO: pass constants
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
|
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
|
||||||
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
fragShaderStageInfo.module = fsShader;
|
data::file_content fsFile({SHADER_DIR + shaderName + ".fs.spv"});
|
||||||
|
fragShaderStageInfo.module = pass.fsShader = createShaderModule(fsFile);
|
||||||
fragShaderStageInfo.pName = "main";
|
fragShaderStageInfo.pName = "main";
|
||||||
fragShaderStageInfo.pSpecializationInfo = nullptr; //TODO: pass constants
|
fragShaderStageInfo.pSpecializationInfo = nullptr; //TODO: pass constants
|
||||||
|
|
||||||
//TODO: geometry
|
//TODO: geometry
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
|
return {vertShaderStageInfo, fragShaderStageInfo};
|
||||||
|
};
|
||||||
|
auto setLayout = [&](Subpass& pass, const std::vector<VkDescriptorSetLayout>& layout, const std::vector<VkPushConstantRange>& push = {}) {
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||||
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipelineLayoutInfo.setLayoutCount = layout.size();
|
||||||
|
pipelineLayoutInfo.pSetLayouts = layout.data();
|
||||||
|
pipelineLayoutInfo.pushConstantRangeCount = push.size();
|
||||||
|
pipelineLayoutInfo.pPushConstantRanges = push.data();
|
||||||
|
|
||||||
|
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, ALLOC, &pass.layout) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create pipeline layout!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
||||||
|
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||||
|
depthStencil.depthTestEnable = VK_TRUE;
|
||||||
|
depthStencil.depthWriteEnable = VK_TRUE;
|
||||||
|
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
|
||||||
|
depthStencil.depthBoundsTestEnable = VK_FALSE; // Restrict sub depth area
|
||||||
|
depthStencil.minDepthBounds = 0.0f;
|
||||||
|
depthStencil.maxDepthBounds = 1.0f;
|
||||||
|
|
||||||
|
depthStencil.stencilTestEnable = VK_FALSE;
|
||||||
|
// Stencil options front/back
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
||||||
|
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||||
|
if constexpr (BLENDING) {
|
||||||
|
colorBlendAttachment.blendEnable = VK_TRUE;
|
||||||
|
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
|
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
|
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
} else {
|
||||||
|
colorBlendAttachment.blendEnable = VK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
||||||
|
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
|
colorBlending.attachmentCount = 1; //NOTE: For multitarget
|
||||||
|
colorBlending.pAttachments = &colorBlendAttachment;
|
||||||
|
colorBlending.logicOpEnable = VK_FALSE;
|
||||||
|
colorBlending.logicOp = VK_LOGIC_OP_COPY;
|
||||||
|
colorBlending.blendConstants[0] = 0.0f;
|
||||||
|
colorBlending.blendConstants[1] = 0.0f;
|
||||||
|
colorBlending.blendConstants[2] = 0.0f;
|
||||||
|
colorBlending.blendConstants[3] = 0.0f;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo trisInputAssembly{};
|
||||||
|
trisInputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
trisInputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
trisInputAssembly.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
// Viewport
|
||||||
|
VkViewport viewport{};
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = (float)info.swapDetails.capabilities.currentExtent.width;
|
||||||
|
viewport.height = (float)info.swapDetails.capabilities.currentExtent.height;
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
|
||||||
|
VkRect2D scissor{};
|
||||||
|
scissor.offset = {0, 0};
|
||||||
|
scissor.extent = info.swapDetails.capabilities.currentExtent;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewportState{};
|
||||||
|
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewportState.viewportCount = 1;
|
||||||
|
viewportState.pViewports = &viewport;
|
||||||
|
viewportState.scissorCount = 1;
|
||||||
|
viewportState.pScissors = &scissor;
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
||||||
|
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
rasterizer.depthClampEnable = VK_FALSE;
|
||||||
|
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||||
|
rasterizer.polygonMode = options.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
||||||
|
rasterizer.lineWidth = 1.0f;
|
||||||
|
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
|
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||||
|
rasterizer.depthBiasEnable = VK_FALSE;
|
||||||
|
rasterizer.depthBiasConstantFactor = 0.0f;
|
||||||
|
rasterizer.depthBiasClamp = 0.0f;
|
||||||
|
rasterizer.depthBiasSlopeFactor = 0.0f;
|
||||||
|
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampling{};
|
||||||
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
multisampling.rasterizationSamples = info.samples;
|
||||||
|
//MAYBE: add option
|
||||||
|
multisampling.sampleShadingEnable = info.features.sampleRateShading && hasSamples;
|
||||||
|
multisampling.minSampleShading = .2f;
|
||||||
|
multisampling.pSampleMask = nullptr;
|
||||||
|
multisampling.alphaToCoverageEnable = VK_FALSE;
|
||||||
|
multisampling.alphaToOneEnable = VK_FALSE;
|
||||||
|
|
||||||
|
{ // World pipeline
|
||||||
|
/*struct Push {
|
||||||
|
alignas(16) glm::mat4 Model;
|
||||||
|
alignas(16) glm::vec4 SphereProj;
|
||||||
|
alignas(4) float Curvature;
|
||||||
|
};*/
|
||||||
|
VkPushConstantRange pushRange{};
|
||||||
|
pushRange.offset = 0;
|
||||||
|
pushRange.size = sizeof(buffer::vk::ModelPush);
|
||||||
|
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
setLayout(worldPass, {voxelDescriptorSet}, {pushRange});
|
||||||
|
auto shaderStages = setShaders(worldPass, "Tris");
|
||||||
|
|
||||||
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;
|
||||||
|
@ -174,108 +303,12 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.size();
|
||||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
|
||||||
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
||||||
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
||||||
inputAssembly.primitiveRestartEnable = VK_FALSE;
|
|
||||||
|
|
||||||
// Viewport
|
|
||||||
VkViewport viewport{};
|
|
||||||
viewport.x = 0.0f;
|
|
||||||
viewport.y = 0.0f;
|
|
||||||
viewport.width = (float)info.swapDetails.capabilities.currentExtent.width;
|
|
||||||
viewport.height = (float)info.swapDetails.capabilities.currentExtent.height;
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 1.0f;
|
|
||||||
|
|
||||||
VkRect2D scissor{};
|
|
||||||
scissor.offset = {0, 0};
|
|
||||||
scissor.extent = info.swapDetails.capabilities.currentExtent;
|
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewportState{};
|
|
||||||
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
||||||
viewportState.viewportCount = 1;
|
|
||||||
viewportState.pViewports = &viewport;
|
|
||||||
viewportState.scissorCount = 1;
|
|
||||||
viewportState.pScissors = &scissor;
|
|
||||||
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
|
||||||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
||||||
rasterizer.depthClampEnable = VK_FALSE;
|
|
||||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
|
||||||
rasterizer.polygonMode = options.wireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
|
|
||||||
rasterizer.lineWidth = 1.0f;
|
|
||||||
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
|
||||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
|
||||||
rasterizer.depthBiasEnable = VK_FALSE;
|
|
||||||
rasterizer.depthBiasConstantFactor = 0.0f;
|
|
||||||
rasterizer.depthBiasClamp = 0.0f;
|
|
||||||
rasterizer.depthBiasSlopeFactor = 0.0f;
|
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling{};
|
|
||||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
||||||
multisampling.rasterizationSamples = info.samples;
|
|
||||||
//MAYBE: add option
|
|
||||||
multisampling.sampleShadingEnable = info.features.sampleRateShading && hasSamples;
|
|
||||||
multisampling.minSampleShading = .2f;
|
|
||||||
multisampling.pSampleMask = nullptr;
|
|
||||||
multisampling.alphaToCoverageEnable = VK_FALSE;
|
|
||||||
multisampling.alphaToOneEnable = VK_FALSE;
|
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{};
|
|
||||||
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
|
||||||
depthStencil.depthTestEnable = VK_TRUE;
|
|
||||||
depthStencil.depthWriteEnable = VK_TRUE;
|
|
||||||
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; //FIXME: LEQUAL for skybox
|
|
||||||
depthStencil.depthBoundsTestEnable = VK_FALSE; // Restrict sub depth area
|
|
||||||
depthStencil.minDepthBounds = 0.0f;
|
|
||||||
depthStencil.maxDepthBounds = 1.0f;
|
|
||||||
|
|
||||||
depthStencil.stencilTestEnable = VK_FALSE;
|
|
||||||
// Stencil options front/back
|
|
||||||
|
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
|
||||||
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
|
||||||
if constexpr (BLENDING) {
|
|
||||||
colorBlendAttachment.blendEnable = VK_TRUE;
|
|
||||||
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
|
||||||
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
||||||
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
|
||||||
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
|
||||||
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
|
||||||
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
|
||||||
} else {
|
|
||||||
colorBlendAttachment.blendEnable = VK_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
|
||||||
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
|
||||||
colorBlending.attachmentCount = 1; //MAYBE: deferred multitarget
|
|
||||||
colorBlending.pAttachments = &colorBlendAttachment;
|
|
||||||
colorBlending.logicOpEnable = VK_FALSE;
|
|
||||||
colorBlending.logicOp = VK_LOGIC_OP_COPY;
|
|
||||||
colorBlending.blendConstants[0] = 0.0f;
|
|
||||||
colorBlending.blendConstants[1] = 0.0f;
|
|
||||||
colorBlending.blendConstants[2] = 0.0f;
|
|
||||||
colorBlending.blendConstants[3] = 0.0f;
|
|
||||||
|
|
||||||
/* MAYBE: dynamic state
|
|
||||||
VkDynamicState dynamicStates[] = {
|
|
||||||
VK_DYNAMIC_STATE_VIEWPORT,
|
|
||||||
VK_DYNAMIC_STATE_LINE_WIDTH};
|
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamicState{};
|
|
||||||
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
|
||||||
dynamicState.dynamicStateCount = 2;
|
|
||||||
dynamicState.pDynamicStates = dynamicStates;
|
|
||||||
*/
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
pipelineInfo.stageCount = 2;
|
pipelineInfo.stageCount = shaderStages.size();
|
||||||
pipelineInfo.pStages = shaderStages;
|
pipelineInfo.pStages = shaderStages.data();
|
||||||
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||||
pipelineInfo.pInputAssemblyState = &inputAssembly;
|
pipelineInfo.pInputAssemblyState = &trisInputAssembly;
|
||||||
pipelineInfo.pViewportState = &viewportState;
|
pipelineInfo.pViewportState = &viewportState;
|
||||||
pipelineInfo.pRasterizationState = &rasterizer;
|
pipelineInfo.pRasterizationState = &rasterizer;
|
||||||
pipelineInfo.pMultisampleState = &multisampling;
|
pipelineInfo.pMultisampleState = &multisampling;
|
||||||
|
@ -283,24 +316,73 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
|
||||||
pipelineInfo.pColorBlendState = &colorBlending;
|
pipelineInfo.pColorBlendState = &colorBlending;
|
||||||
pipelineInfo.pDynamicState = nullptr;
|
pipelineInfo.pDynamicState = nullptr;
|
||||||
|
|
||||||
pipelineInfo.layout = pipelineLayout;
|
pipelineInfo.layout = worldPass.layout;
|
||||||
pipelineInfo.renderPass = renderPass;
|
pipelineInfo.renderPass = renderPass;
|
||||||
pipelineInfo.subpass = 0;
|
pipelineInfo.subpass = 0;
|
||||||
|
|
||||||
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
pipelineInfo.basePipelineIndex = -1;
|
pipelineInfo.basePipelineIndex = -1;
|
||||||
|
|
||||||
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, ALLOC, &graphicsPipeline) != VK_SUCCESS) {
|
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, ALLOC, &worldPass.pipeline) != VK_SUCCESS) {
|
||||||
|
FATAL("Failed to create graphics pipeline!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Sky pipeline
|
||||||
|
VkPushConstantRange pushRange{};
|
||||||
|
pushRange.offset = 0;
|
||||||
|
pushRange.size = sizeof(buffer::vk::SkyPush);
|
||||||
|
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
setLayout(skyPass, {skyDescriptorSet}, {pushRange});
|
||||||
|
auto shaderStages = setShaders(skyPass, "Sky");
|
||||||
|
|
||||||
|
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
|
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
auto bindingDescription = Shape::getBindingDescription();
|
||||||
|
vertexInputInfo.vertexBindingDescriptionCount = 1;
|
||||||
|
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
|
||||||
|
auto attributeDescription = Shape::getAttributeDescription();
|
||||||
|
vertexInputInfo.vertexAttributeDescriptionCount = 1;
|
||||||
|
vertexInputInfo.pVertexAttributeDescriptions = &attributeDescription;
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pipelineInfo.stageCount = shaderStages.size();
|
||||||
|
pipelineInfo.pStages = shaderStages.data();
|
||||||
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||||
|
pipelineInfo.pInputAssemblyState = &trisInputAssembly;
|
||||||
|
pipelineInfo.pViewportState = &viewportState;
|
||||||
|
pipelineInfo.pRasterizationState = &rasterizer;
|
||||||
|
pipelineInfo.pMultisampleState = &multisampling;
|
||||||
|
pipelineInfo.pDepthStencilState = &depthStencil;
|
||||||
|
pipelineInfo.pColorBlendState = &colorBlending;
|
||||||
|
pipelineInfo.pDynamicState = nullptr;
|
||||||
|
|
||||||
|
pipelineInfo.layout = skyPass.layout;
|
||||||
|
pipelineInfo.renderPass = renderPass;
|
||||||
|
pipelineInfo.subpass = 1;
|
||||||
|
|
||||||
|
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
pipelineInfo.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, ALLOC, &skyPass.pipeline) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create graphics pipeline!");
|
FATAL("Failed to create graphics pipeline!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pipeline::~Pipeline() {
|
Pipeline::~Pipeline() {
|
||||||
vkDestroyPipeline(device, graphicsPipeline, ALLOC);
|
auto destroy = [&](Subpass &pass) {
|
||||||
vkDestroyPipelineLayout(device, pipelineLayout, ALLOC);
|
vkDestroyShaderModule(device, pass.fsShader, ALLOC);
|
||||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, ALLOC);
|
vkDestroyShaderModule(device, pass.vsShader, ALLOC);
|
||||||
vkDestroyRenderPass(device, renderPass, ALLOC);
|
vkDestroyPipeline(device, pass.pipeline, ALLOC);
|
||||||
|
vkDestroyPipelineLayout(device, pass.layout, ALLOC);
|
||||||
|
};
|
||||||
|
|
||||||
vkDestroyShaderModule(device, fsShader, ALLOC);
|
destroy(worldPass);
|
||||||
vkDestroyShaderModule(device, vsShader, ALLOC);
|
destroy(skyPass);
|
||||||
|
|
||||||
|
vkDestroyDescriptorSetLayout(device, voxelDescriptorSet, ALLOC);
|
||||||
|
vkDestroyDescriptorSetLayout(device, skyDescriptorSet, ALLOC);
|
||||||
|
vkDestroyRenderPass(device, renderPass, ALLOC);
|
||||||
}
|
}
|
|
@ -4,26 +4,36 @@
|
||||||
|
|
||||||
namespace render::vk {
|
namespace render::vk {
|
||||||
|
|
||||||
|
struct Subpass {
|
||||||
|
VkShaderModule vsShader;
|
||||||
|
VkShaderModule fsShader;
|
||||||
|
VkPipelineLayout layout;
|
||||||
|
VkPipeline pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
class Pipeline final {
|
class Pipeline final {
|
||||||
public:
|
public:
|
||||||
Pipeline(VkDevice, const PhysicalDeviceInfo&, const renderOptions&);
|
Pipeline(VkDevice, const PhysicalDeviceInfo&, const renderOptions&);
|
||||||
~Pipeline();
|
~Pipeline();
|
||||||
|
|
||||||
|
|
||||||
|
// Universe renderpass
|
||||||
constexpr VkRenderPass getRenderPass() const { return renderPass; }
|
constexpr VkRenderPass getRenderPass() const { return renderPass; }
|
||||||
constexpr VkPipeline getPipeline() const { return graphicsPipeline; }
|
// Voxels (world & entity) passes descriptor set
|
||||||
constexpr VkPipelineLayout getLayout() const { return pipelineLayout; }
|
constexpr VkDescriptorSetLayout getVoxelDescriptorSet() const { return voxelDescriptorSet; }
|
||||||
constexpr VkDescriptorSetLayout getDescriptorSet() const { return descriptorSetLayout; }
|
constexpr const Subpass& getWorldPass() const { return worldPass; }
|
||||||
|
constexpr VkDescriptorSetLayout getSkyDescriptorSet() const { return skyDescriptorSet; }
|
||||||
|
constexpr const Subpass& getSkyPass() const { return skyPass; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
|
|
||||||
VkShaderModule vsShader;
|
|
||||||
VkShaderModule fsShader;
|
|
||||||
|
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
|
||||||
VkPipelineLayout pipelineLayout;
|
|
||||||
VkPipeline graphicsPipeline;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
VkDescriptorSetLayout voxelDescriptorSet;
|
||||||
|
VkDescriptorSetLayout skyDescriptorSet;
|
||||||
|
|
||||||
|
Subpass worldPass;
|
||||||
|
Subpass skyPass;
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "UI.hpp"
|
#include "UI.hpp"
|
||||||
#include "../../Window.hpp"
|
#include "../../Window.hpp"
|
||||||
|
#include "../../control/Camera.hpp"
|
||||||
#include "PhysicalDeviceInfo.hpp"
|
#include "PhysicalDeviceInfo.hpp"
|
||||||
#include "Allocator.hpp"
|
#include "Allocator.hpp"
|
||||||
#include "SwapChain.hpp"
|
#include "SwapChain.hpp"
|
||||||
|
@ -34,7 +35,7 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf
|
||||||
if constexpr(VALIDATION_LAYER) {
|
if constexpr(VALIDATION_LAYER) {
|
||||||
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
|
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
createInfo.pfnUserCallback = debugValidationCallback;
|
createInfo.pfnUserCallback = debugValidationCallback;
|
||||||
createInfo.pUserData = nullptr;
|
createInfo.pUserData = nullptr;
|
||||||
|
@ -51,7 +52,7 @@ Renderer::Renderer(VkInstance instance, VkDevice device, const PhysicalDeviceInf
|
||||||
swapChain = std::make_unique<SwapChain>(device, getInfos());
|
swapChain = std::make_unique<SwapChain>(device, getInfos());
|
||||||
pipeline = std::make_unique<Pipeline>(device, getInfos(), options);
|
pipeline = std::make_unique<Pipeline>(device, getInfos(), options);
|
||||||
commandCenter = std::make_unique<CommandCenter>(device, getInfos(), options);
|
commandCenter = std::make_unique<CommandCenter>(device, getInfos(), options);
|
||||||
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().swapDetails.capabilities.currentExtent, options);
|
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().swapDetails.capabilities.currentExtent);
|
||||||
|
|
||||||
{
|
{
|
||||||
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
imageAvailableSemaphores.resize(opt.inFlightFrames);
|
||||||
|
@ -105,7 +106,7 @@ 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, getInfos());
|
swapChain = std::make_unique<SwapChain>(device, getInfos());
|
||||||
pipeline = std::make_unique<Pipeline>(device, getInfos(), options);
|
pipeline = std::make_unique<Pipeline>(device, getInfos(), options);
|
||||||
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().swapDetails.capabilities.currentExtent, options);
|
commandCenter->allocate(swapChain->getImageViews(), *pipeline.get(), getInfos().swapDetails.capabilities.currentExtent);
|
||||||
}
|
}
|
||||||
void Renderer::destroySwapChain() {
|
void Renderer::destroySwapChain() {
|
||||||
commandCenter->free();
|
commandCenter->free();
|
||||||
|
@ -409,6 +410,8 @@ void Renderer::beginFrame() {
|
||||||
|
|
||||||
if (auto newImage = swapChain->acquireNextImage(imageAvailableSemaphores[currentFrame], inFlightFences[currentFrame])) {
|
if (auto newImage = swapChain->acquireNextImage(imageAvailableSemaphores[currentFrame], inFlightFences[currentFrame])) {
|
||||||
currentImage = newImage.value();
|
currentImage = newImage.value();
|
||||||
|
commandCenter->startRecording(currentImage, pipeline->getRenderPass(),
|
||||||
|
getInfos().swapDetails.capabilities.currentExtent, options.clear_color, ViewMatrix, ProjectionMatrix);
|
||||||
allocator->setTracyZone("Submit");
|
allocator->setTracyZone("Submit");
|
||||||
} else {
|
} else {
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
|
@ -416,37 +419,39 @@ void Renderer::beginFrame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<size_t(render::LodModel *const, glm::mat4)> Renderer::beginWorldPass() {
|
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> Renderer::beginWorldPass() {
|
||||||
assert(currentImage < swapChain->getImageViews().size());
|
assert(currentImage < swapChain->getImageViews().size());
|
||||||
|
|
||||||
commandCenter->updateUBO(currentImage);
|
commandCenter->startWorldPass(currentImage, pipeline->getWorldPass());
|
||||||
commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame],
|
commandCenter->recordModel(currentImage);
|
||||||
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
return [&](render::LodModel *const, glm::mat4, glm::vec4, float) {
|
||||||
/*WorldPass->useIt();
|
|
||||||
WorldPass->start(this);*/
|
|
||||||
return [&](render::LodModel *const, glm::mat4) {
|
|
||||||
return 0; //WorldPass->setup(this, model);
|
return 0; //WorldPass->setup(this, model);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
|
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
|
||||||
/*EntityPass->useIt();
|
assert(currentImage < swapChain->getImageViews().size());
|
||||||
EntityPass->start(this);*/
|
|
||||||
|
commandCenter->startEntityPass(currentImage);
|
||||||
return [&](render::Model *const, const std::vector<glm::mat4>&) {
|
return [&](render::Model *const, const std::vector<glm::mat4>&) {
|
||||||
return 0; //EntityPass->setup(this, models);
|
return 0; //EntityPass->setup(this, models);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Renderer::drawIndicatorCube(glm::mat4) {
|
size_t Renderer::drawIndicatorCube(glm::mat4) {
|
||||||
/*IndicatorPass->useIt();
|
assert(currentImage < swapChain->getImageViews().size());
|
||||||
return IndicatorCubeBuffer.draw(IndicatorPass->setup(this, model));*/
|
|
||||||
|
//commandCenter->drawIndicator(model);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::endPass() {
|
void Renderer::postProcess() {
|
||||||
/*if(SkyEnable) {
|
commandCenter->recordPostprocess(currentImage, pipeline->getSkyPass(), options.skybox, ViewMatrix, ProjectionMatrix);
|
||||||
SkyPass->draw(this);
|
}
|
||||||
}*/
|
|
||||||
|
void Renderer::endFrame() {
|
||||||
|
commandCenter->submitGraphics(currentImage, imageAvailableSemaphores[currentFrame],
|
||||||
|
renderFinishedSemaphores[currentFrame], inFlightFences[currentFrame]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::swapBuffer(Window&) {
|
void Renderer::swapBuffer(Window&) {
|
||||||
|
@ -471,17 +476,13 @@ void Renderer::reloadTextures(const std::string&, float, float) {
|
||||||
loadTextures(texturePath, mipMapLOD, anisotropy);*/
|
loadTextures(texturePath, mipMapLOD, anisotropy);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::lookFrom(const Camera&) {
|
void Renderer::lookFrom(const Camera& camera) {
|
||||||
/*ProjectionMatrix = camera.getProjectionMatrix();
|
ProjectionMatrix = camera.getProjectionMatrix();
|
||||||
|
ProjectionMatrix[1][1] *= -1;
|
||||||
ViewMatrix = camera.getViewMatrix();
|
ViewMatrix = camera.getViewMatrix();
|
||||||
FogDepth = camera.getDepth();*/
|
FogDepth = camera.getDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setClearColor(glm::vec4) {
|
void Renderer::setClearColor(glm::vec4 c) {
|
||||||
/*FogColor = c;
|
options.clear_color = c;
|
||||||
glClearColor(c.r, c.g, c.b, c.a);*/
|
|
||||||
}
|
|
||||||
void Renderer::setCurvature(glm::vec4, float) {
|
|
||||||
/*SphereProj = sp;
|
|
||||||
Curvature = c;*/
|
|
||||||
}
|
}
|
|
@ -20,14 +20,14 @@ public:
|
||||||
static _FORCE_INLINE_ Renderer *Get() { return static_cast<Renderer*>(render::Renderer::Get()); }
|
static _FORCE_INLINE_ Renderer *Get() { return static_cast<Renderer*>(render::Renderer::Get()); }
|
||||||
|
|
||||||
void beginFrame() override;
|
void beginFrame() override;
|
||||||
std::function<size_t(render::LodModel *const, glm::mat4)> beginWorldPass() override;
|
std::function<size_t(render::LodModel *const, glm::mat4, glm::vec4, float)> beginWorldPass() override;
|
||||||
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() override;
|
std::function<size_t(render::Model *const, const std::vector<glm::mat4> &)> beginEntityPass() override;
|
||||||
size_t drawIndicatorCube(glm::mat4 model) override;
|
size_t drawIndicatorCube(glm::mat4 model) override;
|
||||||
void endPass() override;
|
void postProcess() override;
|
||||||
void swapBuffer(Window&) override;
|
void endFrame() override;
|
||||||
|
void swapBuffer(Window &) override;
|
||||||
|
|
||||||
void setClearColor(glm::vec4) override;
|
void setClearColor(glm::vec4) override;
|
||||||
void setCurvature(glm::vec4, float) override;
|
|
||||||
|
|
||||||
/// Apply camera matrices
|
/// Apply camera matrices
|
||||||
void lookFrom(const Camera &) override;
|
void lookFrom(const Camera &) override;
|
||||||
|
@ -65,5 +65,9 @@ private:
|
||||||
bool framebufferResized = false;
|
bool framebufferResized = false;
|
||||||
void recreateSwapChain();
|
void recreateSwapChain();
|
||||||
void destroySwapChain();
|
void destroySwapChain();
|
||||||
|
|
||||||
|
glm::mat4 ProjectionMatrix;
|
||||||
|
glm::mat4 ViewMatrix;
|
||||||
|
float FogDepth;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@ Buffer::~Buffer() {
|
||||||
//NOTE: memory_ptr self destroy
|
//NOTE: memory_ptr self destroy
|
||||||
}
|
}
|
||||||
|
|
||||||
memory::ptr createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, const render::data_view view, Buffer::info &out) {
|
memory::ptr render::vk::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, const render::data_view view, Buffer::info &out) {
|
||||||
auto alloc = Allocator::GetDefault();
|
auto alloc = Allocator::GetDefault();
|
||||||
auto device = alloc->getDevice();
|
auto device = alloc->getDevice();
|
||||||
|
|
||||||
|
|
|
@ -88,4 +88,5 @@ private:
|
||||||
memory::ptr memory;
|
memory::ptr memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
memory::ptr createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, const render::data_view view, Buffer::info &out);
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
#include "Buffers.hpp"
|
#include "Buffers.hpp"
|
||||||
#include "../Allocator.hpp"
|
#include "../Allocator.hpp"
|
||||||
#include "../../../../core/utils/logger.hpp"
|
#include "../../../../core/utils/logger.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace render::vk;
|
using namespace render::vk;
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ Texture::~Texture() {
|
||||||
vkDestroySampler(Allocator::GetDefault()->getDevice(), sampler, ALLOC);
|
vkDestroySampler(Allocator::GetDefault()->getDevice(), sampler, ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags properties, const render::data_view data, Image::info& out) {
|
memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags properties, const std::vector<render::data_view>& datas, Image::info& out) {
|
||||||
auto alloc = Allocator::GetDefault();
|
auto alloc = Allocator::GetDefault();
|
||||||
auto device = alloc->getDevice();
|
auto device = alloc->getDevice();
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
info.extent.height = req.size.height;
|
info.extent.height = req.size.height;
|
||||||
info.extent.depth = 1;
|
info.extent.depth = 1;
|
||||||
info.mipLevels = req.mipmapLevels;
|
info.mipLevels = req.mipmapLevels;
|
||||||
info.arrayLayers = 1;
|
info.arrayLayers = req.layers;
|
||||||
info.format = static_cast<VkFormat>(req.format);
|
info.format = static_cast<VkFormat>(req.format);
|
||||||
info.tiling = req.optimal ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
|
info.tiling = req.optimal ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
@ -32,7 +33,13 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
info.samples = static_cast<VkSampleCountFlagBits>(req.samples);
|
info.samples = static_cast<VkSampleCountFlagBits>(req.samples);
|
||||||
info.flags = 0;
|
info.flags = 0;
|
||||||
if (data) {
|
if (req.cube) {
|
||||||
|
info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||||
|
} else if (req.layers > 1) {
|
||||||
|
info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!datas.empty()) {
|
||||||
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,29 +58,46 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
return memory::GetNull();
|
return memory::GetNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) {
|
if (!datas.empty()) {
|
||||||
if(auto staging = WritableBuffer::Create(data.size)) {
|
assert(datas.size() <= req.layers);
|
||||||
staging->write(data, 0);
|
const auto maxSize = [&] {
|
||||||
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, req.mipmapLevels);
|
size_t max = 0;
|
||||||
|
for (auto& data: datas)
|
||||||
|
max = std::max(max, data.size);
|
||||||
|
return max;
|
||||||
|
}();
|
||||||
|
if(auto staging = WritableBuffer::Create(maxSize)) {
|
||||||
|
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, req.mipmapLevels, req.layers);
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
info.initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
alloc->copyBufferToImage(staging->getRef(), out.ref, info.extent.width, info.extent.height, req.mipmapLevels);
|
for (size_t layer = 0; layer < req.layers && layer < datas.size(); layer++) {
|
||||||
|
if(datas[layer].isUsable()) {
|
||||||
|
staging->write(datas[layer], 0);
|
||||||
|
alloc->copyBufferToImage(staging->getRef(), out.ref, info.extent.width, info.extent.height, req.mipmapLevels, layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_E("Cannot allocate staging memory");
|
LOG_E("Cannot allocate staging memory");
|
||||||
return memory::GetNull();
|
return memory::GetNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, static_cast<VkImageLayout>(req.layout), req.mipmapLevels);
|
alloc->transitionImageLayout(out.ref, info.format, info.initialLayout, static_cast<VkImageLayout>(req.layout), req.mipmapLevels, req.layers);
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo{};
|
VkImageViewCreateInfo viewInfo{};
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
viewInfo.image = out.ref;
|
viewInfo.image = out.ref;
|
||||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
if (req.cube) {
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
|
} else if (req.layers > 1) {
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||||
|
} else {
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
}
|
||||||
viewInfo.format = static_cast<VkFormat>(req.format);
|
viewInfo.format = static_cast<VkFormat>(req.format);
|
||||||
viewInfo.subresourceRange.aspectMask = static_cast<VkImageAspectFlags>(req.aspect);
|
viewInfo.subresourceRange.aspectMask = static_cast<VkImageAspectFlags>(req.aspect);
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
viewInfo.subresourceRange.levelCount = req.mipmapLevels;
|
viewInfo.subresourceRange.levelCount = req.mipmapLevels;
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = req.layers;
|
||||||
|
|
||||||
if (vkCreateImageView(device, &viewInfo, ALLOC, &out.view) != VK_SUCCESS) {
|
if (vkCreateImageView(device, &viewInfo, ALLOC, &out.view) != VK_SUCCESS) {
|
||||||
LOG_E("Failed to create texture image view!");
|
LOG_E("Failed to create texture image view!");
|
||||||
|
@ -81,35 +105,17 @@ memory::ptr createImage(const Image::requirement& req, VkMemoryPropertyFlags pro
|
||||||
}
|
}
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
//TODO: createImages
|
|
||||||
|
|
||||||
std::unique_ptr<Image> Image::Create(const requirement & req) {
|
std::unique_ptr<Image> Image::Create(const requirement & req) {
|
||||||
vk::Image::info img;
|
vk::Image::info img;
|
||||||
auto mem = createImage(req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, data_view(), img);
|
auto mem = createImage(req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, {}, img);
|
||||||
if(!mem) {
|
if(!mem) {
|
||||||
FATAL("Cannot create texture image");
|
FATAL("Cannot create texture image");
|
||||||
}
|
}
|
||||||
return std::unique_ptr<Image>(new Image(img.ref, img.view, std::move(mem)));
|
return std::unique_ptr<Image>(new Image(img.ref, img.view, std::move(mem)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sampling& props) {
|
VkSampler createSampler(const Texture::sampling& props, uint32_t mipmapLevels) {
|
||||||
auto device = Allocator::GetDefault()->getDevice();
|
|
||||||
|
|
||||||
std::vector<unsigned char> data;
|
|
||||||
auto header = [&] {
|
|
||||||
if (auto header = render::Image::Read(path, data)) {
|
|
||||||
return header.value();
|
|
||||||
}
|
|
||||||
FATAL("Cannot read texture");
|
|
||||||
}();
|
|
||||||
|
|
||||||
vk::Image::info img;
|
|
||||||
auto mem = createImage(requirement::Texture(header),
|
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, data, img);
|
|
||||||
if(!mem) {
|
|
||||||
FATAL("Cannot create texture image");
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSamplerCreateInfo samplerInfo{};
|
VkSamplerCreateInfo samplerInfo{};
|
||||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
samplerInfo.magFilter = props.magLinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
samplerInfo.magFilter = props.magLinear ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||||
|
@ -138,16 +144,108 @@ std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sa
|
||||||
samplerInfo.mipmapMode = props.minLinear ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
samplerInfo.mipmapMode = props.minLinear ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
samplerInfo.mipLodBias = 0.0f; //TODO:
|
samplerInfo.mipLodBias = 0.0f; //TODO:
|
||||||
samplerInfo.minLod = 0.0f;
|
samplerInfo.minLod = 0.0f;
|
||||||
samplerInfo.maxLod = props.mipmap ? header.mipmapLevels : 0.0f;
|
samplerInfo.maxLod = props.mipmap ? mipmapLevels : 0.0f;
|
||||||
|
|
||||||
if (props.mipmap && header.mipmapLevels <= 1) {
|
if (props.mipmap && mipmapLevels <= 1) {
|
||||||
LOG_D("Sampler requires mipmap but image does not");
|
LOG_D("Sampler requires mipmap but image does not");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
if (vkCreateSampler(device, &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
if (vkCreateSampler(Allocator::GetDefault()->getDevice(), &samplerInfo, ALLOC, &sampler) != VK_SUCCESS) {
|
||||||
FATAL("Failed to create texture sampler!");
|
FATAL("Failed to create texture sampler!");
|
||||||
}
|
}
|
||||||
|
return sampler;
|
||||||
|
}
|
||||||
|
|
||||||
return std::unique_ptr<Texture>(new Texture(sampler, img.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, img.ref, std::move(mem)));
|
std::unique_ptr<Texture> Texture::LoadFromFile(const std::string& path, const sampling& props) {
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
auto header = [&] {
|
||||||
|
if (auto header = render::Image::Read(path, data)) {
|
||||||
|
return header.value();
|
||||||
|
}
|
||||||
|
FATAL("Cannot read texture");
|
||||||
|
}();
|
||||||
|
|
||||||
|
vk::Image::info img;
|
||||||
|
auto mem = createImage(requirement::Texture(header),
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, {data}, img);
|
||||||
|
if(!mem) {
|
||||||
|
FATAL("Cannot create texture image");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<Texture>(new Texture(createSampler(props, header.mipmapLevels), img.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, img.ref, std::move(mem)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TextureCube> TextureCube::LoadFromFiles(const std::array<std::string, 6>& paths, const sampling& props) {
|
||||||
|
std::vector<std::vector<unsigned char>> datas;
|
||||||
|
std::vector<data_view> views;
|
||||||
|
views.reserve(6);
|
||||||
|
datas.resize(1);
|
||||||
|
auto header = [&] {
|
||||||
|
if (auto header = render::Image::Read(paths.at(0), datas.at(0))) {
|
||||||
|
views.push_back(datas.at(0));
|
||||||
|
return header.value();
|
||||||
|
}
|
||||||
|
FATAL("Cannot read first texture");
|
||||||
|
}();
|
||||||
|
datas.resize(paths.size());
|
||||||
|
for (size_t i = 1; i < paths.size(); i++) {
|
||||||
|
if(!render::Image::Read(paths.at(i), datas.at(i)).has_value()) {
|
||||||
|
FATAL("Cannot read depth texture");
|
||||||
|
}
|
||||||
|
views.push_back(datas.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::Image::info img;
|
||||||
|
auto mem = createImage(requirement::Texture(header, paths.size(), true),
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, views, img);
|
||||||
|
if(!mem) {
|
||||||
|
FATAL("Cannot create texture cube image");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<TextureCube>(new TextureCube(createSampler(props, header.mipmapLevels), img.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, img.ref, std::move(mem)));
|
||||||
|
}
|
||||||
|
std::unique_ptr<TextureCube> TextureCube::LoadFromFiles(const std::string& prefix, const sampling& props) {
|
||||||
|
const std::array<std::string, 6> faces {
|
||||||
|
"right",
|
||||||
|
"left",
|
||||||
|
"top",
|
||||||
|
"bottom",
|
||||||
|
"front",
|
||||||
|
"back"
|
||||||
|
};
|
||||||
|
std::array<std::string, 6> paths;
|
||||||
|
std::transform(faces.begin(), faces.end(), paths.begin(),
|
||||||
|
[prefix](const std::string &face) -> std::string { return prefix + "." + face + ".dds"; });
|
||||||
|
return LoadFromFiles(paths, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TextureArray> TextureArray::LoadFromFiles(const std::vector<std::string>& paths, const sampling& props) {
|
||||||
|
std::vector<std::vector<unsigned char>> datas;
|
||||||
|
std::vector<data_view> views;
|
||||||
|
datas.resize(1);
|
||||||
|
views.reserve(6);
|
||||||
|
auto header = [&] {
|
||||||
|
if (auto header = render::Image::Read(paths.at(0), datas.at(0))) {
|
||||||
|
views.push_back(datas.at(0));
|
||||||
|
return header.value();
|
||||||
|
}
|
||||||
|
FATAL("Cannot read first texture");
|
||||||
|
}();
|
||||||
|
datas.reserve(paths.size());
|
||||||
|
for (size_t i = 1; i < paths.size(); i++) {
|
||||||
|
if(!render::Image::Read(paths.at(i), datas.at(i)).has_value()) {
|
||||||
|
FATAL("Cannot read depth texture");
|
||||||
|
}
|
||||||
|
views.push_back(datas.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::Image::info img;
|
||||||
|
auto mem = createImage(requirement::Texture(header, paths.size()),
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, views, img);
|
||||||
|
if(!mem) {
|
||||||
|
FATAL("Cannot create texture cube image");
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<TextureArray>(new TextureArray(paths.size(), createSampler(props, header.mipmapLevels), img.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, img.ref, std::move(mem)));
|
||||||
}
|
}
|
|
@ -44,4 +44,24 @@ protected:
|
||||||
const VkDescriptorImageInfo descriptor;
|
const VkDescriptorImageInfo descriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TextureCube: public render::TextureCube, public Texture {
|
||||||
|
public:
|
||||||
|
/// Looks for .right.dds, .left.dds, .top.dds, .bottom.dds, .front.dds, .back.dds
|
||||||
|
static std::unique_ptr<TextureCube> LoadFromFiles(const std::string& prefix, const sampling&);
|
||||||
|
static std::unique_ptr<TextureCube> LoadFromFiles(const std::array<std::string, 6>& paths, const sampling&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextureCube(VkSampler sampler, VkImageView view, VkImageLayout layout, VkImage ref, memory::ptr memory):
|
||||||
|
Texture(sampler, view, layout, ref, std::move(memory)) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextureArray: public render::TextureArray, public Texture {
|
||||||
|
public:
|
||||||
|
static std::unique_ptr<TextureArray> LoadFromFiles(const std::vector<std::string>&, const sampling&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextureArray(uint32_t size, VkSampler sampler, VkImageView view, VkImageLayout layout, VkImage ref, memory::ptr memory):
|
||||||
|
render::TextureArray(size), Texture(sampler, view, layout, ref, std::move(memory)) { }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "Models.hpp"
|
||||||
|
|
||||||
|
using namespace render::vk;
|
||||||
|
|
||||||
|
std::unique_ptr<Shape> Shape::Create(const std::vector<glm::vec3>& vertices) {
|
||||||
|
vk::Buffer::info tmp;
|
||||||
|
data_view view(vertices);
|
||||||
|
auto mem = createBuffer(view.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, view, tmp);
|
||||||
|
return std::unique_ptr<Shape>(new Shape(tmp.ref, std::move(mem), vertices.size()));
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../api/Models.hpp"
|
||||||
|
#include "Buffers.hpp"
|
||||||
|
|
||||||
|
namespace render::vk {
|
||||||
|
|
||||||
|
/// Positions only buffer
|
||||||
|
class Shape final: public Buffer {
|
||||||
|
public:
|
||||||
|
const size_t size;
|
||||||
|
|
||||||
|
static std::unique_ptr<Shape> Create(const std::vector<glm::vec3>&);
|
||||||
|
|
||||||
|
static VkVertexInputBindingDescription getBindingDescription() {
|
||||||
|
VkVertexInputBindingDescription description{};
|
||||||
|
description.binding = 0;
|
||||||
|
description.stride = sizeof(glm::vec3);
|
||||||
|
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
static VkVertexInputAttributeDescription getAttributeDescription() {
|
||||||
|
VkVertexInputAttributeDescription attributeDescription{};
|
||||||
|
attributeDescription.binding = 0;
|
||||||
|
attributeDescription.location = 0;
|
||||||
|
attributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
attributeDescription.offset = 0;
|
||||||
|
return attributeDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Shape(VkBuffer ref, memory::ptr mem, size_t size):
|
||||||
|
Buffer(ref, std::move(mem)), size(size) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*class Indicator final: public render::Indicator {
|
||||||
|
public:
|
||||||
|
Indicator(const std::vector<glm::vec3>&, const std::vector<glm::vec4>&);
|
||||||
|
~Indicator();
|
||||||
|
|
||||||
|
size_t draw();
|
||||||
|
size_t drawInstanced(size_t count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t size;
|
||||||
|
GLuint vertexBufferId;
|
||||||
|
GLuint colorBufferId;
|
||||||
|
|
||||||
|
void enableAttribs();
|
||||||
|
void disableAttribs();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Model final: public render::Model {
|
||||||
|
public:
|
||||||
|
Model(const Data&);
|
||||||
|
~Model();
|
||||||
|
|
||||||
|
size_t draw();
|
||||||
|
size_t drawInstanced(size_t count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t indexSize;
|
||||||
|
GLuint vertexBufferId;
|
||||||
|
GLuint indexBufferId;
|
||||||
|
};
|
||||||
|
class LodModel final: public render::LodModel {
|
||||||
|
public:
|
||||||
|
LodModel(const LodData&);
|
||||||
|
~LodModel();
|
||||||
|
|
||||||
|
static void MakeDefault();
|
||||||
|
|
||||||
|
size_t draw();
|
||||||
|
size_t drawInstanced(size_t count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint vertexBufferId;
|
||||||
|
GLuint indexBufferId;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
}
|
|
@ -54,7 +54,6 @@ const std::vector<uint16_t> indices = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBufferObject {
|
struct UniformBufferObject {
|
||||||
alignas(16) glm::mat4 model;
|
|
||||||
alignas(16) glm::mat4 view;
|
alignas(16) glm::mat4 view;
|
||||||
alignas(16) glm::mat4 proj;
|
alignas(16) glm::mat4 proj;
|
||||||
|
|
||||||
|
@ -69,4 +68,13 @@ struct UniformBufferObject {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ModelPush {
|
||||||
|
alignas(16) glm::mat4 model;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkyPush {
|
||||||
|
alignas(16) glm::mat4 view;
|
||||||
|
alignas(16) glm::mat4 proj;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue