Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Select Git revision
  • 119-graphicspipeline-refactoring
  • 129-projekte-und-assets-auslagern
  • 132-denoising-module
  • 143-ar-vr-support-via-openxr
  • 43-multi-threading
  • 91-compute-first-network
  • 95-arm64-raspberry-pi-4-support
  • develop
  • master
  • optimizations
  • 0.1.0
  • 0.2.0
12 results
Show changes
Showing
with 303 additions and 200 deletions
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=0, binding=0) buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout(location = 0) out vec3 geomNormal;
void main() {
gl_Position = vec4(inPosition, 1.0);
geomNormal = inNormal;
gl_Position = vec4(vertices[gl_VertexIndex].position, 1.0);
geomNormal = vertices[gl_VertexIndex].normal;
}
\ No newline at end of file
......@@ -10,7 +10,7 @@ layout(location = 0) in vec3 geomNormal[];
layout(location = 0) out vec3 passNormal;
layout(location = 1) out vec3 passEdge;
layout(set=1, binding=0) uniform clipBuffer {
layout(set=2, binding=0) uniform clipBuffer {
float clipLimit;
float clipX;
float clipY;
......
......@@ -101,14 +101,7 @@ int main(int argc, const char** argv) {
{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/red.frag" }
}, nullptr);
const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
}
const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(1);
const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(2);
auto clipDescriptorSetLayout = core.createDescriptorSetLayout(clipBindings);
auto clipDescriptorSet = core.createDescriptorSet(clipDescriptorSetLayout);
......@@ -148,7 +141,6 @@ int main(int argc, const char** argv) {
}
});
const vkcv::VertexLayout sceneLayout { bindings };
const auto& material0 = scene.getMaterial(0);
const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
......@@ -156,8 +148,11 @@ int main(int argc, const char** argv) {
UINT32_MAX,
UINT32_MAX,
scenePass,
{sceneLayout},
{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
{
scene.getDescriptorSetLayout(),
material0.getDescriptorSetLayout(),
clipDescriptorSetLayout
},
true
};
......@@ -166,8 +161,11 @@ int main(int argc, const char** argv) {
UINT32_MAX,
UINT32_MAX,
linePass,
{sceneLayout},
{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
{
scene.getDescriptorSetLayout(),
material0.getDescriptorSetLayout(),
clipDescriptorSetLayout
},
true
};
......@@ -241,7 +239,7 @@ int main(int argc, const char** argv) {
vkcv::DrawcallInfo& drawcallInfo) {
pushConstants.appendDrawcall(MVP);
drawcallInfo.descriptorSets.push_back(
vkcv::DescriptorSetUsage(1, clipDescriptorSet)
vkcv::DescriptorSetUsage(2, clipDescriptorSet)
);
};
......
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inUV;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=1, binding=0) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout(location = 0) out vec3 passNormal;
layout(location = 1) out vec2 passUV;
......@@ -14,7 +21,7 @@ layout( push_constant ) uniform constants{
};
void main() {
gl_Position = mvp * vec4(inPosition, 1.0);
passNormal = (model * vec4(inNormal, 0)).xyz;
passUV = inUV;
gl_Position = mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
passNormal = (model * vec4(vertices[gl_VertexIndex].normal, 0)).xyz;
passUV = vec2(vertices[gl_VertexIndex].u, vertices[gl_VertexIndex].v);
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=0, binding=0) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout(location = 0) out vec4 passNDC;
layout(location = 1) out vec4 passNDCPrevious;
......@@ -12,7 +21,7 @@ layout( push_constant ) uniform constants{
};
void main() {
gl_Position = mvp * vec4(inPosition, 1.0);
gl_Position = mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
passNDC = gl_Position;
passNDCPrevious = mvpPrevious * vec4(inPosition, 1.0);
passNDCPrevious = mvpPrevious * vec4(vertices[gl_VertexIndex].position, 1.0);
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=0, binding=0) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout( push_constant ) uniform constants{
mat4 viewProjection;
};
void main() {
gl_Position = viewProjection * vec4(inPosition, 0.0);
gl_Position = viewProjection * vec4(vertices[gl_VertexIndex].position, 0.0);
gl_Position.w = gl_Position.z;
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=0, binding=0) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout( push_constant ) uniform constants{
mat4 viewProjection;
......@@ -12,11 +21,11 @@ layout(location = 0) out vec4 passNDC;
layout(location = 1) out vec4 passNDCPrevious;
void main() {
gl_Position = viewProjection * vec4(inPosition, 0.0);
gl_Position = viewProjection * vec4(vertices[gl_VertexIndex].position, 0.0);
gl_Position.w = gl_Position.z;
passNDC = gl_Position;
passNDCPrevious = viewProjectionPrevious * vec4(inPosition, 0.0);
passNDCPrevious = viewProjectionPrevious * vec4(vertices[gl_VertexIndex].position, 0.0);
passNDCPrevious.w = passNDCPrevious.z;
}
\ No newline at end of file
......@@ -85,7 +85,9 @@ void App::run() {
auto frameStartTime = std::chrono::system_clock::now();
const auto appStartTime = std::chrono::system_clock::now();
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
const vkcv::DrawcallInfo skyDrawcall(m_cubeMesh.mesh, {}, 1);
const vkcv::DrawcallInfo skyDrawcall(m_cubeMesh.mesh, {
vkcv::DescriptorSetUsage(0, m_cubeMesh.descSet)
}, 1);
vkcv::gui::GUI gui(m_core, m_windowHandle);
......@@ -218,7 +220,9 @@ void App::run() {
std::vector<vkcv::DrawcallInfo> prepassSceneDrawcalls;
for (const Object& obj : sceneObjects) {
prepassSceneDrawcalls.push_back(vkcv::DrawcallInfo(obj.meshResources.mesh, {}));
prepassSceneDrawcalls.push_back(vkcv::DrawcallInfo(obj.meshResources.mesh, {
vkcv::DescriptorSetUsage(0, obj.meshResources.descSet)
}));
}
m_core.recordDrawcallsToCmdStream(
......@@ -260,8 +264,12 @@ void App::run() {
std::vector<vkcv::DrawcallInfo> forwardSceneDrawcalls;
for (const Object& obj : sceneObjects) {
forwardSceneDrawcalls.push_back(vkcv::DrawcallInfo(
obj.meshResources.mesh,
{ vkcv::DescriptorSetUsage(0, m_meshPass.descriptorSet) }));
obj.meshResources.mesh,
{
vkcv::DescriptorSetUsage(0, m_meshPass.descriptorSet),
vkcv::DescriptorSetUsage(1, obj.meshResources.descSet),
}
));
}
m_core.recordDrawcallsToCmdStream(
......
......@@ -3,6 +3,11 @@
#include <vkcv/asset/asset_loader.hpp>
#include <vkcv/shader/GLSLCompiler.hpp>
struct vertex_t {
float positionU [4];
float normalV [4];
};
bool loadMesh(vkcv::Core& core, const std::filesystem::path& path, MeshResources* outMesh) {
assert(outMesh);
......@@ -20,38 +25,80 @@ bool loadMesh(vkcv::Core& core, const std::filesystem::path& path, MeshResources
}
assert(!scene.vertexGroups.empty());
auto& vertexData = scene.vertexGroups[0].vertexBuffer;
auto& indexData = scene.vertexGroups[0].indexBuffer;
vkcv::Buffer vertexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::VERTEX,
vertexData.data.size(),
vkcv::Buffer vertexBuffer = core.createBuffer<vertex_t>(
vkcv::BufferType::STORAGE,
scene.vertexGroups[0].numVertices,
vkcv::BufferMemoryType::DEVICE_LOCAL);
std::vector<vertex_t> vertices;
vertices.reserve(vertexBuffer.getCount());
for (const auto& attribute : scene.vertexGroups[0].vertexBuffer.attributes) {
if (attribute.componentType != vkcv::asset::ComponentType::FLOAT32) {
continue;
}
size_t offset = attribute.offset;
for (size_t i = 0; i < vertexBuffer.getCount(); i++) {
const auto *data = reinterpret_cast<const float*>(
scene.vertexGroups[0].vertexBuffer.data.data() + offset
);
switch (attribute.type) {
case vkcv::asset::PrimitiveType::POSITION:
memcpy(vertices[i].positionU, data, sizeof(float) * attribute.componentCount);
break;
case vkcv::asset::PrimitiveType::NORMAL:
memcpy(vertices[i].normalV, data, sizeof(float) * attribute.componentCount);
break;
case vkcv::asset::PrimitiveType::TEXCOORD_0:
if (attribute.componentCount != 2) {
break;
}
vertices[i].positionU[3] = data[0];
vertices[i].normalV[3] = data[1];
break;
default:
break;
}
offset += attribute.stride;
}
}
vertexBuffer.fill(vertices);
vkcv::Buffer indexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::INDEX,
indexData.data.size(),
scene.vertexGroups[0].indexBuffer.data.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL);
vertexBuffer.fill(vertexData.data);
indexBuffer.fill(indexData.data);
indexBuffer.fill(scene.vertexGroups[0].indexBuffer.data);
outMesh->vertexBuffer = vertexBuffer.getHandle();
outMesh->indexBuffer = indexBuffer.getHandle();
auto& attributes = vertexData.attributes;
std::sort(attributes.begin(), attributes.end(),
[](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
});
const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
outMesh->mesh = vkcv::Mesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), scene.vertexGroups[0].numIndices);
outMesh->mesh = vkcv::Mesh(indexBuffer.getVulkanHandle(), scene.vertexGroups[0].numIndices);
vkcv::DescriptorBindings descriptorBindings;
descriptorBindings.insert(std::make_pair(0, vkcv::DescriptorBinding {
0,
vkcv::DescriptorType::STORAGE_BUFFER,
1,
vkcv::ShaderStage::VERTEX,
false,
false
}));
outMesh->descSetLayout = core.createDescriptorSetLayout(descriptorBindings);
outMesh->descSet = core.createDescriptorSet(outMesh->descSetLayout);
core.writeDescriptorSet(
outMesh->descSet,
vkcv::DescriptorWrites().writeStorageBuffer(0, outMesh->vertexBuffer)
);
return true;
}
......@@ -116,31 +163,27 @@ bool loadGraphicPass(
shaderProgram.addShader(shaderStage, path);
});
const std::vector<vkcv::VertexAttachment> vertexAttachments = shaderProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
}
const vkcv::VertexLayout vertexLayout { bindings };
const auto descriptorBindings = shaderProgram.getReflectedDescriptors();
const bool hasDescriptor = descriptorBindings.size() > 0;
std::vector<vkcv::DescriptorSetLayoutHandle> descriptorSetLayouts = {};
if (hasDescriptor)
{
outPassHandles->descriptorSetLayout = core.createDescriptorSetLayout(descriptorBindings.at(0));
descriptorSetLayouts.reserve(descriptorBindings.size());
for (size_t i = 0; i < descriptorBindings.size(); i++) {
descriptorSetLayouts.push_back(core.createDescriptorSetLayout(descriptorBindings.at(i)));
}
outPassHandles->descriptorSetLayout = descriptorSetLayouts[0];
outPassHandles->descriptorSet = core.createDescriptorSet(outPassHandles->descriptorSetLayout);
descriptorSetLayouts.push_back(outPassHandles->descriptorSetLayout);
}
vkcv::GraphicsPipelineConfig pipelineConfig{
shaderProgram,
UINT32_MAX,
UINT32_MAX,
outPassHandles->renderPass,
{ vertexLayout },
descriptorSetLayouts,
true
};
......@@ -148,7 +191,8 @@ bool loadGraphicPass(
outPassHandles->pipeline = core.createGraphicsPipeline(pipelineConfig);
if (!outPassHandles->pipeline) {
vkcv_log(vkcv::LogLevel::ERROR, "Error: Could not create graphics pipeline");
vkcv_log(vkcv::LogLevel::ERROR, "Error: Could not create graphics pipeline [%s]",
vertexPath.c_str());
return false;
}
......
......@@ -24,6 +24,8 @@ struct MeshResources {
vkcv::Mesh mesh;
vkcv::BufferHandle vertexBuffer;
vkcv::BufferHandle indexBuffer;
vkcv::DescriptorSetLayoutHandle descSetLayout;
vkcv::DescriptorSetHandle descSet;
};
// loads position, uv and normal of the first mesh in a scene
......
......@@ -8,8 +8,8 @@ layout(location = 2) in flat uint passDrawIndex;
layout(location = 0) out vec3 outColor;
layout(set=0, binding=0) uniform sampler standardSampler;
layout(set=0, binding=2) uniform texture2D baseColorTex[];
layout(set=0, binding=2) uniform sampler standardSampler;
layout(set=0, binding=3) uniform texture2D baseColorTex[];
void main()
......
......@@ -2,11 +2,18 @@
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shader_draw_parameters : enable
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inUV;
struct vertex_t {
vec3 position;
float u;
vec3 normal;
float v;
};
layout(std430, set=0, binding=0) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout(std430, binding=1) readonly buffer uModel {
layout(std430, set=0, binding=1) readonly buffer uModel {
mat4 modelMatrix[];
};
......@@ -20,8 +27,8 @@ layout( push_constant ) uniform constants{
void main()
{
gl_Position = vp * modelMatrix[gl_DrawID] * vec4(inPosition, 1.0);
passNormal = inNormal;
passUV = inUV;
gl_Position = vp * modelMatrix[gl_DrawID] * vec4(vertices[gl_VertexIndex].position, 1.0);
passNormal = vertices[gl_VertexIndex].normal;
passUV = vec2(vertices[gl_VertexIndex].u, vertices[gl_VertexIndex].v);
passDrawIndex = gl_DrawID;
}
\ No newline at end of file
......@@ -72,9 +72,8 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) {
struct Vertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 uv;
glm::vec4 positionU;
glm::vec4 normalV;
};
struct CompiledMaterial
......@@ -130,12 +129,19 @@ void interleaveScene(vkcv::asset::Scene scene,
const size_t uvOffset = uvAttribute.offset + uvStride * i;
Vertex v;
const glm::vec2& uv = *reinterpret_cast<const glm::vec2*>(
&(vertexData[uvOffset])
);
const glm::vec3& position = *reinterpret_cast<const glm::vec3*>(
&(vertexData[positionOffset])
);
v.position = *reinterpret_cast<const glm::vec3*>(&(vertexData[positionOffset]));
v.normal = *reinterpret_cast<const glm::vec3*>(&(vertexData[normalOffset]));
v.uv = *reinterpret_cast<const glm::vec3*>(&(vertexData[uvOffset]));
v.positionU = glm::vec4(position, uv[0]);
v.normalV = glm::vec4(*reinterpret_cast<const glm::vec3*>(&(vertexData[normalOffset])), uv[1]);
glm::vec3 posWorld = glm::make_mat4(mesh.modelMatrix.data()) * glm::vec4(v.position, 1);
glm::vec3 posWorld = glm::make_mat4(mesh.modelMatrix.data()) * glm::vec4(position, 1);
max_pos.x = glm::max(max_pos.x, posWorld.x);
max_pos.y = glm::max(max_pos.y, posWorld.y);
......@@ -362,12 +368,6 @@ int main(int argc, const char** argv) {
cullingProgram.addShader(shaderStage, path);
});
// vertex layout for the pipeline. (assumed to be) used by all sponza meshes.
const std::vector<vkcv::VertexAttachment> vertexAttachments = sponzaProgram.getVertexAttachments();
const vkcv::VertexLayout sponzaVertexLayout {
{ vkcv::createVertexBinding(0, { vertexAttachments }) }
};
std::vector<uint8_t> compiledVertexBuffer; // IGNORED, since the vertex buffer is not interleaved!
std::vector<uint8_t> compiledIndexBuffer;
......@@ -388,16 +388,16 @@ int main(int argc, const char** argv) {
compiledBoundingBoxBuffer);
std::vector<Vertex> compiledInterleavedVertexBuffer;
for(auto& vertexGroup : interleavedVertices )
{
for(auto& vertexGroup : interleavedVertices ) {
compiledInterleavedVertexBuffer.insert(compiledInterleavedVertexBuffer.end(),vertexGroup.begin(),vertexGroup.end());
}
auto vkCompiledVertexBuffer = core.createBuffer<Vertex>(
vkcv::BufferType::VERTEX,
vkcv::BufferType::STORAGE,
compiledInterleavedVertexBuffer.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL
);
);
vkCompiledVertexBuffer.fill(compiledInterleavedVertexBuffer.data());
auto vkCompiledIndexBuffer = core.createBuffer<uint8_t>(
......@@ -429,16 +429,12 @@ int main(int argc, const char** argv) {
);
modelBuffer.fill(modelMatrix);
const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize> (0), vkCompiledVertexBuffer.getVulkanHandle() )
};
const vkcv::Mesh compiledMesh(vertexBufferBindings, vkCompiledIndexBuffer.getVulkanHandle(), 0, vkcv::IndexBitCount::Bit32);
const vkcv::Mesh compiledMesh(vkCompiledIndexBuffer.getVulkanHandle(), 0, vkcv::IndexBitCount::Bit32);
//assert(compiledMaterial.baseColor.size() == compiledMaterial.metalRough.size());
vkcv::DescriptorBindings descriptorBindings = sponzaProgram.getReflectedDescriptors().at(0);
descriptorBindings[2].descriptorCount = compiledMaterial.baseColor.size();
descriptorBindings[3].descriptorCount = compiledMaterial.baseColor.size();
vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(descriptorBindings);
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
......@@ -451,15 +447,16 @@ int main(int argc, const char** argv) {
);
vkcv::DescriptorWrites setWrites;
setWrites.writeStorageBuffer(0, vkCompiledVertexBuffer.getHandle());
setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
setWrites.writeSampler(2, standardSampler);
std::vector<vkcv::SampledImageDescriptorWrite> textureArrayWrites;
for(uint32_t i = 0; i < compiledMaterial.baseColor.size(); i++)
{
setWrites.writeSampledImage(2, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
setWrites.writeSampledImage(3, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
}
setWrites.writeSampler(0, standardSampler);
setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
core.writeDescriptorSet(descriptorSet, setWrites);
const vkcv::GraphicsPipelineConfig sponzaPipelineConfig {
......@@ -467,7 +464,6 @@ int main(int argc, const char** argv) {
UINT32_MAX,
UINT32_MAX,
passHandle,
{sponzaVertexLayout},
{ descriptorSetLayout },
true
};
......
......@@ -4,8 +4,16 @@
#include "common.inc"
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
struct vertex_t {
vec3 position;
float pad0;
vec3 normal;
float pad1;
};
layout(std430, set=0, binding=1) readonly buffer buffer_vertexBuffer {
vertex_t vertices [];
};
layout(location = 0) out vec3 passNormal;
layout(location = 1) out uint dummyOutput;
......@@ -22,8 +30,8 @@ layout( push_constant ) uniform constants{
void main() {
gl_Position = objectMatrices[matrixIndex].mvp * vec4(inPosition, 1.0);
passNormal = inNormal;
gl_Position = objectMatrices[matrixIndex].mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
passNormal = vertices[gl_VertexIndex].normal;
dummyOutput = padding * 0; // padding must be used, else compiler shrinks constant size
}
\ No newline at end of file
......@@ -75,6 +75,13 @@ CameraPlanes computeCameraPlanes(const vkcv::camera::Camera& camera) {
return cameraPlanes;
}
struct vertex_t {
float position [3];
float pad0;
float normal [3];
float pad1;
};
int main(int argc, const char** argv) {
const char* applicationName = "Mesh shader";
......@@ -103,12 +110,61 @@ int main(int argc, const char** argv) {
assert(!mesh.vertexGroups.empty());
auto vertexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::VERTEX,
mesh.vertexGroups[0].vertexBuffer.data.size(),
auto vertexBuffer = core.createBuffer<vertex_t>(
vkcv::BufferType::STORAGE,
mesh.vertexGroups[0].numVertices,
vkcv::BufferMemoryType::DEVICE_LOCAL
);
vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
std::vector<vertex_t> vertices;
vertices.reserve(vertexBuffer.getCount());
const vkcv::asset::VertexAttribute* attr_position = nullptr;
const vkcv::asset::VertexAttribute* attr_normal = nullptr;
for (const auto& attribute : mesh.vertexGroups[0].vertexBuffer.attributes) {
if (attribute.componentType != vkcv::asset::ComponentType::FLOAT32) {
continue;
}
switch (attribute.type) {
case vkcv::asset::PrimitiveType::POSITION:
attr_position = &attribute;
break;
case vkcv::asset::PrimitiveType::NORMAL:
attr_normal = &attribute;
break;
default:
break;
}
size_t offset = attribute.offset;
for (size_t i = 0; i < vertexBuffer.getCount(); i++) {
const auto *data = reinterpret_cast<const float*>(
mesh.vertexGroups[0].vertexBuffer.data.data() + offset
);
switch (attribute.type) {
case vkcv::asset::PrimitiveType::POSITION:
memcpy(vertices[i].position, data, sizeof(float) * attribute.componentCount);
break;
case vkcv::asset::PrimitiveType::NORMAL:
memcpy(vertices[i].normal, data, sizeof(float) * attribute.componentCount);
break;
default:
break;
}
offset += attribute.stride;
}
}
vertexBuffer.fill(vertices);
if ((nullptr == attr_position) || (nullptr == attr_normal)) {
return 1;
}
auto indexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::INDEX,
......@@ -117,20 +173,8 @@ int main(int argc, const char** argv) {
);
indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
// format data for mesh shader
auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
});
const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
const auto& bunny = mesh.vertexGroups[0];
std::vector<vkcv::meshlet::Vertex> interleavedVertices = vkcv::meshlet::convertToVertices(bunny.vertexBuffer.data, bunny.numVertices, attributes[0], attributes[1]);
std::vector<vkcv::meshlet::Vertex> interleavedVertices = vkcv::meshlet::convertToVertices(bunny.vertexBuffer.data, bunny.numVertices, *attr_position, *attr_normal);
// mesh shader buffers
const auto& assetLoaderIndexBuffer = mesh.vertexGroups[0].indexBuffer;
std::vector<uint32_t> indexBuffer32Bit = vkcv::meshlet::assetLoaderIndicesTo32BitIndices(assetLoaderIndexBuffer.data, assetLoaderIndexBuffer.type);
......@@ -194,13 +238,6 @@ int main(int argc, const char** argv) {
bunnyShaderProgram.addShader(shaderStage, path);
});
const std::vector<vkcv::VertexAttachment> vertexAttachments = bunnyShaderProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
}
const vkcv::VertexLayout bunnyLayout { bindings };
vkcv::DescriptorSetLayoutHandle vertexShaderDescriptorSetLayout = core.createDescriptorSetLayout(bunnyShaderProgram.getReflectedDescriptors().at(0));
vkcv::DescriptorSetHandle vertexShaderDescriptorSet = core.createDescriptorSet(vertexShaderDescriptorSetLayout);
......@@ -209,7 +246,6 @@ int main(int argc, const char** argv) {
UINT32_MAX,
UINT32_MAX,
renderPass,
{ bunnyLayout },
{ vertexShaderDescriptorSetLayout },
true
};
......@@ -223,6 +259,7 @@ int main(int argc, const char** argv) {
vkcv::DescriptorWrites vertexShaderDescriptorWrites;
vertexShaderDescriptorWrites.writeStorageBuffer(0, matrixBuffer.getHandle());
vertexShaderDescriptorWrites.writeStorageBuffer(1, vertexBuffer.getHandle());
core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
......@@ -252,14 +289,12 @@ int main(int argc, const char** argv) {
vkcv::DescriptorSetLayoutHandle meshShaderDescriptorSetLayout = core.createDescriptorSetLayout(meshShaderProgram.getReflectedDescriptors().at(0));
vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet(meshShaderDescriptorSetLayout);
const vkcv::VertexLayout meshShaderLayout(bindings);
const vkcv::GraphicsPipelineConfig meshShaderPipelineDefinition{
meshShaderProgram,
UINT32_MAX,
UINT32_MAX,
renderPass,
{meshShaderLayout},
{meshShaderDescriptorSetLayout},
true
};
......@@ -297,7 +332,7 @@ int main(int argc, const char** argv) {
vkcv::ImageHandle swapchainImageHandle = vkcv::ImageHandle::createSwapchainImageHandle();
const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices, vkcv::IndexBitCount::Bit32);
const vkcv::Mesh renderMesh(indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices, vkcv::IndexBitCount::Bit32);
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
......
#version 460 core
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 particle;
struct Particle
{
vec3 position;
......@@ -29,17 +27,23 @@ layout(location = 2) out float passlifeTime;
void main()
{
vec2 positions[3] = {
vec2(-0.012f, 0.012f),
vec2(0.012f, 0.012f),
vec2(0.0f, -0.012f)
};
int id = gl_InstanceIndex;
passVelocity = inParticle[id].velocity;
passlifeTime = inParticle[id].lifeTime;
// particle position in view space
vec4 positionView = view * vec4(inParticle[id].position, 1);
// by adding the triangle position in view space the mesh is always camera facing
positionView.xyz += particle;
positionView.xyz += vec3(positions[gl_VertexIndex], 0.0f);
// multiply with projection matrix for final position
gl_Position = projection * positionView;
// 0.01 corresponds to vertex position size in main
float normalizationDivider = 0.012;
passTriangleCoordinates = particle.xy / normalizationDivider;
passTriangleCoordinates = positions[gl_VertexIndex] / normalizationDivider;
}
\ No newline at end of file
......@@ -79,14 +79,6 @@ int main(int argc, const char **argv) {
vkcv::DescriptorSetLayoutHandle computeDescriptorSetLayout = core.createDescriptorSetLayout(computeShaderProgram.getReflectedDescriptors().at(0));
vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeDescriptorSetLayout);
const std::vector<vkcv::VertexAttachment> computeVertexAttachments = computeShaderProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> computeBindings;
for (size_t i = 0; i < computeVertexAttachments.size(); i++) {
computeBindings.push_back(vkcv::createVertexBinding(i, { computeVertexAttachments[i] }));
}
const vkcv::VertexLayout computeLayout { computeBindings };
vkcv::ShaderProgram particleShaderProgram{};
compiler.compile(vkcv::ShaderStage::VERTEX, "shaders/shader.vert", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
particleShaderProgram.addShader(shaderStage, path);
......@@ -99,39 +91,16 @@ int main(int argc, const char **argv) {
particleShaderProgram.getReflectedDescriptors().at(0));
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
vkcv::Buffer<glm::vec3> vertexBuffer = core.createBuffer<glm::vec3>(
vkcv::BufferType::VERTEX,
3
);
const std::vector<vkcv::VertexAttachment> vertexAttachments = particleShaderProgram.getVertexAttachments();
const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
vkcv::VertexBufferBinding(0, vertexBuffer.getVulkanHandle())};
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::createVertexBinding(i, {vertexAttachments[i]}));
}
const vkcv::VertexLayout particleLayout { bindings };
vkcv::GraphicsPipelineConfig particlePipelineDefinition{
particleShaderProgram,
UINT32_MAX,
UINT32_MAX,
particlePass,
{particleLayout},
{descriptorSetLayout},
true
};
particlePipelineDefinition.m_blendMode = vkcv::BlendMode::Additive;
const std::vector<glm::vec3> vertices = {glm::vec3(-0.012, 0.012, 0),
glm::vec3(0.012, 0.012, 0),
glm::vec3(0, -0.012, 0)};
vertexBuffer.fill(vertices);
vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition);
vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline({
......@@ -163,6 +132,7 @@ int main(int argc, const char **argv) {
vkcv::DescriptorWrites setWrites;
setWrites.writeUniformBuffer(0, color.getHandle()).writeUniformBuffer(1, position.getHandle());
setWrites.writeStorageBuffer(2, particleBuffer.getHandle());
core.writeDescriptorSet(descriptorSet, setWrites);
vkcv::DescriptorWrites computeWrites;
......@@ -177,7 +147,7 @@ int main(int argc, const char **argv) {
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
const vkcv::Mesh renderMesh({vertexBufferBindings}, particleIndexBuffer.getVulkanHandle(),
const vkcv::Mesh renderMesh(particleIndexBuffer.getVulkanHandle(),
particleIndexBuffer.getCount());
vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet);
......
......@@ -81,14 +81,6 @@ int main(int argc, const char** argv) {
vkcv::DescriptorSetLayoutHandle computeDescriptorSetLayout = core.createDescriptorSetLayout(computeDescriptorBindings);
vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeDescriptorSetLayout);
const std::vector<vkcv::VertexAttachment> computeVertexAttachments = computeShaderProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> computeBindings;
for (size_t i = 0; i < computeVertexAttachments.size(); i++) {
computeBindings.push_back(vkcv::createVertexBinding(i, { computeVertexAttachments[i] }));
}
const vkcv::VertexLayout computeLayout { computeBindings };
/*
* create the scene
......@@ -178,7 +170,6 @@ int main(int argc, const char** argv) {
UINT32_MAX,
UINT32_MAX,
safrPass,
{},
{ descriptorSetLayout },
true
};
......@@ -200,7 +191,7 @@ int main(int argc, const char** argv) {
auto start = std::chrono::system_clock::now();
const vkcv::Mesh renderMesh({}, safrIndexBuffer.getVulkanHandle(), 3);
const vkcv::Mesh renderMesh(safrIndexBuffer.getVulkanHandle(), 3);
vkcv::DescriptorSetUsage descriptorUsage(0, descriptorSet);
vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage }, 1);
......
#version 460 core
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 particle;
struct Particle
{
vec3 position;
......@@ -33,17 +31,25 @@ layout(location = 1) out vec3 passVelocity;
void main()
{
const float particle_size = 0.02f;
vec2 positions[3] = {
vec2(-particle_size, particle_size),
vec2(particle_size, particle_size),
vec2(0.0f, -particle_size)
};
int id = gl_InstanceIndex;
passVelocity = inParticle1[id].velocity;
// particle position in view space
vec4 positionView = view * vec4(inParticle1[id].position, 1);
// by adding the triangle position in view space the mesh is always camera facing
positionView.xyz += particle;
positionView.xyz += vec3(positions[gl_VertexIndex], 0.0f);
// multiply with projection matrix for final position
gl_Position = projection * positionView;
// 0.01 corresponds to vertex position size in main
float normalizationDivider = 0.012;
passTriangleCoordinates = particle.xy / normalizationDivider;
float normalizationDivider = particle_size;
passTriangleCoordinates = positions[gl_VertexIndex] / normalizationDivider;
}
\ No newline at end of file
......@@ -53,14 +53,6 @@ void main() {
vec3 out_force = inParticle[id].force;
float out_density = inParticle[id].density;
float out_pressure = inParticle[id].pressure;
if (length(vel_new) > 100.f)
{
vel_new = normalize(vel_new)*50;
out_density = 0.01f;
out_pressure = 0.01f;
out_force = gravity * vec3(-gravityDir.x,gravityDir.y,gravityDir.z);
}
vec3 pos_new = inParticle[id].position + (dt * vel_new);
......