Skip to content
Snippets Groups Projects
Commit 220d58d8 authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#106] Initial project

parent ab528a93
No related branches found
No related tags found
1 merge request!89Resolve "Indirect Dispatch"
Pipeline #26633 passed
Showing
with 380 additions and 2 deletions
...@@ -29,8 +29,19 @@ namespace vkcv { ...@@ -29,8 +29,19 @@ namespace vkcv {
}; };
struct Mesh { struct Mesh {
inline Mesh(std::vector<VertexBufferBinding> vertexBufferBindings, vk::Buffer indexBuffer, size_t indexCount, IndexBitCount indexBitCount = IndexBitCount::Bit16) noexcept
: vertexBufferBindings(vertexBufferBindings), indexBuffer(indexBuffer), indexCount(indexCount), indexBitCount(indexBitCount){} inline Mesh(){}
inline Mesh(
std::vector<VertexBufferBinding> vertexBufferBindings,
vk::Buffer indexBuffer,
size_t indexCount,
IndexBitCount indexBitCount = IndexBitCount::Bit16) noexcept
:
vertexBufferBindings(vertexBufferBindings),
indexBuffer(indexBuffer),
indexCount(indexCount),
indexBitCount(indexBitCount) {}
std::vector<VertexBufferBinding> vertexBufferBindings; std::vector<VertexBufferBinding> vertexBufferBindings;
vk::Buffer indexBuffer; vk::Buffer indexBuffer;
......
...@@ -6,3 +6,4 @@ add_subdirectory(first_scene) ...@@ -6,3 +6,4 @@ add_subdirectory(first_scene)
add_subdirectory(particle_simulation) add_subdirectory(particle_simulation)
add_subdirectory(voxelization) add_subdirectory(voxelization)
add_subdirectory(mesh_shader) add_subdirectory(mesh_shader)
add_subdirectory(indirect_dispatch)
cmake_minimum_required(VERSION 3.16)
project(indirect_dispatch)
# setting c++ standard for the project
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# this should fix the execution path to load local files from the project
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# adding source files to the project
add_executable(indirect_dispatch src/main.cpp)
target_sources(indirect_dispatch PRIVATE
src/App.hpp
src/App.cpp
src/AppConfig.hpp
src/AppSetup.hpp
src/AppSetup.cpp)
# this should fix the execution path to load local files from the project (for MSVC)
if(MSVC)
set_target_properties(indirect_dispatch PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
set_target_properties(indirect_dispatch PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
# in addition to setting the output directory, the working directory has to be set
# by default visual studio sets the working directory to the build directory, when using the debugger
set_target_properties(indirect_dispatch PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
# including headers of dependencies and the VkCV framework
target_include_directories(indirect_dispatch SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include})
# linking with libraries from all dependencies and the VkCV framework
target_link_libraries(indirect_dispatch vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_testing vkcv_camera vkcv_shader_compiler vkcv_gui)
\ No newline at end of file
File added
Source diff could not be displayed: it is stored in LFS. Options to address this: view the blob.
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 passNormal;
layout(location = 0) out vec3 outColor;
void main() {
outColor = passNormal * 0.5 + 0.5;
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 0) out vec3 passNormal;
layout( push_constant ) uniform constants{
mat4 mvp;
};
void main() {
gl_Position = mvp * vec4(inPosition, 1.0);
passNormal = inNormal;
}
\ No newline at end of file
#include "App.hpp"
#include "AppConfig.hpp"
#include <chrono>
App::App() :
m_applicationName("Indirect Dispatch"),
m_windowWidth(AppConfig::defaultWindowWidth),
m_windowHeight(AppConfig::defaultWindowHeight),
m_window(vkcv::Window::create(
m_applicationName,
m_windowWidth,
m_windowHeight,
true)),
m_core(vkcv::Core::create(
m_window,
m_applicationName,
VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer },
{},
{ "VK_KHR_swapchain" })),
m_cameraManager(m_window){
m_isInitialized = false;
}
bool App::initialize() {
if (!loadMeshGraphicPass(m_core, &m_meshPassHandles))
return false;
if (!loadSphereMesh(m_core, &m_sphereMesh))
return false;
m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight);
const int cameraIndex = m_cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
m_cameraManager.getCamera(cameraIndex).setPosition(glm::vec3(0, 0, -3));
m_isInitialized = true;
}
void App::run() {
if (!m_isInitialized) {
vkcv_log(vkcv::LogLevel::WARNING, "Application is not initialized, app should be initialized explicitly to check for errors");
if (!initialize()) {
vkcv_log(vkcv::LogLevel::ERROR, "Emergency initialization failed, exiting");
return;
}
}
auto frameStartTime = std::chrono::system_clock::now();
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
const vkcv::DrawcallInfo sphereDrawcall(m_sphereMesh.mesh, {}, 1);
while (m_window.isWindowOpen()) {
vkcv::Window::pollEvents();
if (m_window.getHeight() == 0 || m_window.getWidth() == 0)
continue;
uint32_t swapchainWidth, swapchainHeight;
if (!m_core.beginFrame(swapchainWidth, swapchainHeight))
continue;
const bool hasResolutionChanged = (swapchainWidth != m_windowWidth) || (swapchainHeight != m_windowHeight);
if (hasResolutionChanged) {
m_windowWidth = swapchainWidth;
m_windowHeight = swapchainHeight;
m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight);
}
auto frameEndTime = std::chrono::system_clock::now();
auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(frameEndTime - frameStartTime);
frameStartTime = frameEndTime;
m_cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
const glm::mat4 mvp = m_cameraManager.getActiveCamera().getMVP();
vkcv::PushConstants pushConstants(sizeof(glm::mat4));
pushConstants.appendDrawcall(mvp);
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, m_renderTargets.depthBuffer };
const vkcv::CommandStreamHandle cmdStream = m_core.createCommandStream(vkcv::QueueType::Graphics);
m_core.recordDrawcallsToCmdStream(
cmdStream,
m_meshPassHandles.renderPass,
m_meshPassHandles.pipeline,
pushConstants,
{ sphereDrawcall },
renderTargets);
m_core.prepareSwapchainImageForPresent(cmdStream);
m_core.submitCommandStream(cmdStream);
m_core.endFrame();
}
}
\ No newline at end of file
#pragma once
#include <vkcv/Core.hpp>
#include <vkcv/camera/CameraManager.hpp>
#include "AppSetup.hpp"
class App {
public:
App();
bool initialize();
void run();
private:
const char* m_applicationName;
bool m_isInitialized;
int m_windowWidth;
int m_windowHeight;
vkcv::Window m_window;
vkcv::Core m_core;
vkcv::camera::CameraManager m_cameraManager;
MeshResources m_sphereMesh;
GraphicPassHandles m_meshPassHandles;
RenderTargets m_renderTargets;
};
\ No newline at end of file
#pragma once
#include "vulkan/vulkan.hpp"
namespace AppConfig{
const int defaultWindowWidth = 1280;
const int defaultWindowHeight = 720;
const vk::Format depthBufferFormat = vk::Format::eD32Sfloat;
}
\ No newline at end of file
#include "AppSetup.hpp"
#include "AppConfig.hpp"
#include <vkcv/asset/asset_loader.hpp>
#include <vkcv/shader/GLSLCompiler.hpp>
bool loadSphereMesh(vkcv::Core& core, MeshResources* outMesh) {
assert(outMesh);
vkcv::asset::Scene sphereScene;
const int meshLoadResult = vkcv::asset::loadScene("resources/models/Sphere.gltf", sphereScene);
if (meshLoadResult != 1) {
vkcv_log(vkcv::LogLevel::ERROR, "Mesh loading failed");
return false;
}
if (sphereScene.meshes.size() < 1) {
vkcv_log(vkcv::LogLevel::ERROR, "Sphere mesh scene does not contain any vertex groups");
return false;
}
assert(!sphereScene.vertexGroups.empty());
auto& sphereVertexData = sphereScene.vertexGroups[0].vertexBuffer;
auto& sphereIndexData = sphereScene.vertexGroups[0].indexBuffer;
vkcv::Buffer vertexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::VERTEX,
sphereVertexData.data.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL);
vkcv::Buffer indexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::INDEX,
sphereIndexData.data.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL);
vertexBuffer.fill(sphereVertexData.data);
indexBuffer.fill(sphereIndexData.data);
outMesh->vertexBuffer = vertexBuffer.getHandle();
outMesh->indexBuffer = indexBuffer.getHandle();
auto& attributes = sphereVertexData.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()) };
outMesh->mesh = vkcv::Mesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), sphereScene.vertexGroups[0].numIndices);
return true;
}
bool loadMeshGraphicPass(vkcv::Core& core, GraphicPassHandles* outPassHandles) {
assert(outPassHandles);
const vkcv::AttachmentDescription present_color_attachment(
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
core.getSwapchain().getFormat());
const vkcv::AttachmentDescription depth_attachment(
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
AppConfig::depthBufferFormat);
vkcv::PassConfig meshPassDefinition({ present_color_attachment, depth_attachment });
outPassHandles->renderPass = core.createPass(meshPassDefinition);
if (!outPassHandles->renderPass) {
vkcv_log(vkcv::LogLevel::ERROR, "Error: Could not create renderpass");
return false;
}
vkcv::ShaderProgram meshProgram;
vkcv::shader::GLSLCompiler compiler;
compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"),
[&meshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
meshProgram.addShader(shaderStage, path);
});
compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"),
[&meshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
meshProgram.addShader(shaderStage, path);
});
const std::vector<vkcv::VertexAttachment> vertexAttachments = meshProgram.getVertexAttachments();
std::vector<vkcv::VertexBinding> bindings;
for (size_t i = 0; i < vertexAttachments.size(); i++) {
bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
}
const vkcv::VertexLayout meshVertexLayout(bindings);
const vkcv::PipelineConfig meshPipelineConfig{
meshProgram,
UINT32_MAX,
UINT32_MAX,
outPassHandles->renderPass,
{ meshVertexLayout },
{},
true };
outPassHandles->pipeline = core.createGraphicsPipeline(meshPipelineConfig);
if (!outPassHandles->pipeline) {
vkcv_log(vkcv::LogLevel::ERROR, "Error: Could not create graphics pipeline");
return false;
}
return true;
}
RenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height) {
RenderTargets targets;
targets.depthBuffer = core.createImage(
AppConfig::depthBufferFormat,
width,
height,
1,
false).getHandle();
return targets;
}
\ No newline at end of file
#pragma once
#include <vkcv/Core.hpp>
struct RenderTargets {
vkcv::ImageHandle depthBuffer;
};
struct GraphicPassHandles {
vkcv::PipelineHandle pipeline;
vkcv::PassHandle renderPass;
};
struct MeshResources {
vkcv::Mesh mesh;
vkcv::BufferHandle vertexBuffer;
vkcv::BufferHandle indexBuffer;
};
bool loadSphereMesh(vkcv::Core& core, MeshResources* outMesh);
bool loadMeshGraphicPass(vkcv::Core& core, GraphicPassHandles* outPassHandles);
RenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height);
\ No newline at end of file
#include "App.hpp"
int main(int argc, const char** argv) {
App app;
if (!app.initialize()) {
std::cerr << "Application initialization failed, exiting" << std::endl;
}
app.run();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment