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

[#70] Merge develop

parents bfeb93f8 d97962c3
No related branches found
No related tags found
1 merge request!57Resolve "Basic voxelization"
Pipeline #25831 passed
Showing
with 790 additions and 80 deletions
<<<<<<< HEAD
=======
>>>>>>> develop
# IDE specific files
.project
.cproject
......@@ -19,3 +15,6 @@ cmake-build-release/
*.exe
*.ilk
*.pdb
# GUI configuration files
imgui.ini
......@@ -14,7 +14,7 @@ build_ubuntu_gcc:
- $RUN =~ /\bubuntu.*/i || $RUN =~ /\ball.*/i
stage: build
tags:
- ubuntu-gcc
- ubuntu-gcc-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 10m
......@@ -37,11 +37,11 @@ build_win10_msvc:
- $RUN =~ /\bwin.*/i || $RUN =~ /\ball.*/i
stage: build
tags:
- win10-msvc
- win10-msvc-cached
variables:
GIT_SUBMODULE_STRATEGY: recursive
timeout: 10m
retry: 1
retry: 0
script:
- cd 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\'
- .\Launch-VsDevShell.ps1
......
......@@ -19,3 +19,6 @@
[submodule "modules/shader_compiler/lib/glslang"]
path = modules/shader_compiler/lib/glslang
url = https://github.com/KhronosGroup/glslang.git
[submodule "modules/gui/lib/imgui"]
path = modules/gui/lib/imgui
url = https://github.com/ocornut/imgui.git
......@@ -41,15 +41,15 @@ if (vkcv_build_debug)
endif()
endif()
# configure everything to use the required dependencies
include(${vkcv_config}/Libraries.cmake)
# add modules as targets
add_subdirectory(modules)
# add source files for compilation
include(${vkcv_config}/Sources.cmake)
# configure everything to use the required dependencies
include(${vkcv_config}/Libraries.cmake)
message("-- Libraries: [ ${vkcv_libraries} ]")
message("-- Flags: [ ${vkcv_flags} ]")
......
......@@ -32,8 +32,8 @@ set(vkcv_sources
${vkcv_include}/vkcv/Logger.hpp
${vkcv_include}/vkcv/SwapChain.hpp
${vkcv_source}/vkcv/SwapChain.cpp
${vkcv_include}/vkcv/Swapchain.hpp
${vkcv_source}/vkcv/Swapchain.cpp
${vkcv_include}/vkcv/ShaderStage.hpp
......
......@@ -8,7 +8,7 @@
#include <vulkan/vulkan.hpp>
#include "vkcv/Context.hpp"
#include "vkcv/SwapChain.hpp"
#include "vkcv/Swapchain.hpp"
#include "vkcv/Window.hpp"
#include "vkcv/PassConfig.hpp"
#include "vkcv/Handles.hpp"
......@@ -41,6 +41,7 @@ namespace vkcv
QueueType queueType;
std::vector<vk::Semaphore> waitSemaphores;
std::vector<vk::Semaphore> signalSemaphores;
vk::Fence fence;
};
class Core final
......@@ -52,7 +53,7 @@ namespace vkcv
*
* @param context encapsulates various Vulkan objects
*/
Core(Context &&context, Window &window, const SwapChain& swapChain, std::vector<vk::ImageView> imageViews,
Core(Context &&context, Window &window, const Swapchain& swapChain, std::vector<vk::ImageView> imageViews,
const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
// explicit destruction of default constructor
Core() = delete;
......@@ -61,8 +62,8 @@ namespace vkcv
Context m_Context;
SwapChain m_swapchain;
const Window& m_window;
Swapchain m_swapchain;
Window& m_window;
std::unique_ptr<PassManager> m_PassManager;
std::unique_ptr<PipelineManager> m_PipelineManager;
......@@ -76,9 +77,9 @@ namespace vkcv
SyncResources m_SyncResources;
uint32_t m_currentSwapchainImageIndex;
std::function<void(int, int)> e_resizeHandle;
event_handle<int,int> e_resizeHandle;
static std::vector<vk::ImageView> createSwapchainImageViews( Context &context, SwapChain& swapChain);
static std::vector<vk::ImageView> createSwapchainImageViews( Context &context, Swapchain& swapChain);
public:
/**
......@@ -118,6 +119,9 @@ namespace vkcv
[[nodiscard]]
const Context &getContext() const;
[[nodiscard]]
const Swapchain& getSwapchain() const;
/**
* Creates a #Core with given @p applicationName and @p applicationVersion for your application.
......@@ -248,8 +252,6 @@ namespace vkcv
*/
void endFrame();
vk::Format getSwapchainImageFormat();
/**
* Submit a command buffer to any queue of selected type. The recording can be customized by a
* custom record-command-function. If the command submission has finished, an optional finish-function
......@@ -277,5 +279,8 @@ namespace vkcv
void prepareImageForStorage(const CommandStreamHandle cmdStream, const ImageHandle image);
void recordImageMemoryBarrier(const CommandStreamHandle cmdStream, const ImageHandle image);
void recordBufferMemoryBarrier(const CommandStreamHandle cmdStream, const BufferHandle buffer);
};
const vk::ImageView& getSwapchainImageView() const;
};
}
......@@ -3,10 +3,18 @@
#include <functional>
namespace vkcv {
template<typename... T>
struct event_handle {
uint32_t id;
};
template<typename... T>
struct event_function {
typedef std::function<void(T...)> type;
event_handle<T...> handle;
type callback;
};
/**
......@@ -16,7 +24,8 @@ namespace vkcv {
template<typename... T>
struct event {
private:
std::vector<typename event_function<T...>::type> m_handles;
std::vector< event_function<T...> > m_functions;
uint32_t m_id_counter;
public:
......@@ -25,28 +34,34 @@ namespace vkcv {
* @param arguments of the given function
*/
void operator()(T... arguments) {
for (auto &handle : this->m_handles) {
handle(arguments...);
for (auto &function : this->m_functions) {
function.callback(arguments...);
}
}
/**
* adds a function handle to the event to be called
* @param handle of the function
* @param callback of the function
* @return handle of the function
*/
typename event_function<T...>::type add(typename event_function<T...>::type handle) {
this->m_handles.push_back(handle);
return handle;
event_handle<T...> add(typename event_function<T...>::type callback) {
event_function<T...> function;
function.handle = { m_id_counter++ };
function.callback = callback;
this->m_functions.push_back(function);
return function.handle;
}
/**
* removes a function handle of the event
* @param handle of the function
*/
void remove(typename event_function<T...>::type handle) {
this->m_handles.erase(
remove(this->m_handles.begin(), this->m_handles.end(), handle),
this->m_handles.end()
void remove(event_handle<T...> handle) {
this->m_functions.erase(
std::remove_if(this->m_functions.begin(), this->m_functions.end(), [&handle](auto function){
return (handle.id == function.handle.id);
}),
this->m_functions.end()
);
}
......
......@@ -29,9 +29,6 @@ namespace vkcv {
[[nodiscard]]
uint32_t getDepth() const;
[[nodiscard]]
vk::ImageLayout getLayout() const;
[[nodiscard]]
vkcv::ImageHandle getHandle() const;
......
......@@ -7,8 +7,9 @@
namespace vkcv
{
class SwapChain final {
class Swapchain final {
private:
friend class Core;
struct Surface
{
......@@ -21,10 +22,10 @@ namespace vkcv
Surface m_Surface;
vk::SwapchainKHR m_Swapchain;
vk::Format m_SwapchainFormat;
vk::ColorSpaceKHR m_SwapchainColorSpace;
vk::PresentModeKHR m_SwapchainPresentMode;
uint32_t m_SwapchainImageCount;
vk::Format m_Format;
vk::ColorSpaceKHR m_ColorSpace;
vk::PresentModeKHR m_PresentMode;
uint32_t m_ImageCount;
vk::Extent2D m_Extent;
......@@ -39,16 +40,36 @@ namespace vkcv
* @param format
*/
// TODO:
SwapChain(const Surface &surface,
Swapchain(const Surface &surface,
vk::SwapchainKHR swapchain,
vk::Format format,
vk::ColorSpaceKHR colorSpace,
vk::PresentModeKHR presentMode,
uint32_t imageCount,
vk::Extent2D extent) noexcept;
/**
* TODO
*
* @return
*/
bool shouldUpdateSwapchain() const;
/**
* TODO
*
* context
* window
*/
void updateSwapchain(const Context &context, const Window &window);
/**
*
*/
void signalSwapchainRecreation();
public:
SwapChain(const SwapChain& other);
Swapchain(const Swapchain& other);
/**
* @return The swapchain linked with the #SwapChain class
......@@ -69,7 +90,7 @@ namespace vkcv
* @return gets the chosen swapchain format
*/
[[nodiscard]]
vk::Format getSwapchainFormat() const;
vk::Format getFormat() const;
/**
* creates a swap chain object out of the given window and the given context
......@@ -77,37 +98,17 @@ namespace vkcv
* @param context of the application
* @return returns an object of swapChain
*/
static SwapChain create(const Window &window, const Context &context);
static Swapchain create(const Window &window, const Context &context);
/**
* Destructor of SwapChain
*/
virtual ~SwapChain();
virtual ~Swapchain();
/**
* @return number of images in swapchain
*/
uint32_t getImageCount();
/**
* TODO
*
* @return
*/
bool shouldUpdateSwapchain() const;
/**
* TODO
*
* context
* window
*/
void updateSwapchain(const Context &context, const Window &window);
/**
*
*/
void signalSwapchainRecreation();
uint32_t getImageCount() const;
/**
* TODO
......
......@@ -13,16 +13,19 @@ struct GLFWwindow;
namespace vkcv {
class Window final {
private:
GLFWwindow *m_window;
/**
class Window {
protected:
GLFWwindow *m_window;
/**
*
* @param GLFWwindow of the class
*/
explicit Window(GLFWwindow *window);
explicit Window(GLFWwindow *window);
static GLFWwindow* createGLFWWindow(const char *windowTitle, int width, int height, bool resizable);
private:
/**
* mouse callback for moving the mouse on the screen
* @param[in] window The window that received the event.
......@@ -58,6 +61,13 @@ namespace vkcv {
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were held down.
*/
static void onKeyEvent(GLFWwindow *callbackWindow, int key, int scancode, int action, int mods);
/**
* char callback for any typed character
* @param[in] window The window that received the event
* @param[in] c The character that got typed
*/
static void onCharEvent(GLFWwindow *callbackWindow, unsigned int c);
public:
/**
......@@ -95,6 +105,7 @@ namespace vkcv {
event< double, double > e_mouseScroll;
event< int, int > e_resize;
event< int, int, int, int > e_key;
event< unsigned int > e_char;
/**
* returns the current window
......
......@@ -2,5 +2,6 @@
# Add new modules here:
add_subdirectory(asset_loader)
add_subdirectory(camera)
add_subdirectory(gui)
add_subdirectory(shader_compiler)
add_subdirectory(testing)
......@@ -25,11 +25,11 @@ namespace vkcv::camera {
*/
class CameraManager{
private:
std::function<void(int, int, int, int)> m_keyHandle;
std::function<void(double, double)> m_mouseMoveHandle;
std::function<void(double, double)> m_mouseScrollHandle;
std::function<void(int, int, int)> m_mouseButtonHandle;
std::function<void(int, int)> m_resizeHandle;
event_handle<int, int, int, int> m_keyHandle;
event_handle<double, double> m_mouseMoveHandle;
event_handle<double, double> m_mouseScrollHandle;
event_handle<int, int, int> m_mouseButtonHandle;
event_handle<int, int> m_resizeHandle;
Window& m_window;
std::vector<Camera> m_cameras;
......
......@@ -14,7 +14,13 @@ namespace vkcv::camera {
m_lastY = static_cast<float>(window.getHeight()) / 2.0f;
}
CameraManager::~CameraManager() {}
CameraManager::~CameraManager() {
m_window.e_key.remove(m_keyHandle);
m_window.e_mouseMove.remove(m_mouseMoveHandle);
m_window.e_mouseScroll.remove(m_mouseScrollHandle);
m_window.e_mouseButton.remove(m_mouseButtonHandle);
m_window.e_resize.remove(m_resizeHandle);
}
void CameraManager::bindCameraToEvents() {
m_keyHandle = m_window.e_key.add( [&](int key, int scancode, int action, int mods) { this->keyCallback(key, scancode, action, mods); });
......
cmake_minimum_required(VERSION 3.16)
project(vkcv_gui)
# setting c++ standard for the module
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(vkcv_gui_source ${PROJECT_SOURCE_DIR}/src)
set(vkcv_gui_include ${PROJECT_SOURCE_DIR}/include)
# Add source and header files to the module
set(vkcv_gui_sources
${vkcv_gui_include}/vkcv/gui/GUI.hpp
${vkcv_gui_source}/vkcv/gui/GUI.cpp
)
# Setup some path variables to load libraries
set(vkcv_gui_lib lib)
set(vkcv_gui_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_gui_lib})
# Check and load IMGUI
include(config/ImGui.cmake)
# adding source files to the module
add_library(vkcv_gui STATIC ${vkcv_gui_sources} ${vkcv_imgui_sources})
# link the required libraries to the module
target_link_libraries(vkcv_gui ${vkcv_gui_libraries} vkcv ${vkcv_libraries})
# including headers of dependencies and the VkCV framework
target_include_directories(vkcv_gui SYSTEM BEFORE PRIVATE ${vkcv_gui_includes} ${vkcv_include} ${vkcv_includes})
# add the own include directory for public headers
target_include_directories(vkcv_gui BEFORE PUBLIC ${vkcv_gui_include} ${vkcv_imgui_includes})
if (EXISTS "${vkcv_gui_lib_path}/imgui")
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_glfw.cpp)
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/backends/imgui_impl_vulkan.cpp )
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui.cpp)
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_draw.cpp)
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_demo.cpp)
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_tables.cpp)
list(APPEND vkcv_imgui_sources ${vkcv_gui_lib_path}/imgui/imgui_widgets.cpp)
list(APPEND vkcv_imgui_includes ${vkcv_gui_lib}/imgui)
list(APPEND vkcv_imgui_includes ${vkcv_gui_lib}/imgui/backend)
list(APPEND vkcv_gui_include ${vkcv_gui_lib})
else()
message(WARNING "IMGUI is required..! Update the submodules!")
endif ()
#pragma once
#include "imgui/imgui.h"
#include "imgui/backends/imgui_impl_glfw.h"
#include "imgui/backends/imgui_impl_vulkan.h"
#include <vkcv/Core.hpp>
#include <vkcv/Window.hpp>
namespace vkcv::gui {
class GUI final {
private:
Window& m_window;
Core& m_core;
const Context& m_context;
ImGuiContext* m_gui_context;
vk::DescriptorPool m_descriptor_pool;
vk::RenderPass m_render_pass;
event_handle<int,int,int> f_mouseButton;
event_handle<double,double> f_mouseScroll;
event_handle<int,int,int,int> f_key;
event_handle<unsigned int> f_char;
public:
/**
* Constructor of a new instance of ImGui management
*
* @param core Valid #Core instance of the framework
* @param window Valid #Window instance of the framework
*/
GUI(Core& core, Window& window);
GUI(const GUI& other) = delete;
GUI(GUI&& other) = delete;
GUI& operator=(const GUI& other) = delete;
GUI& operator=(GUI&& other) = delete;
/**
* Destructor of a #GUI instance
*/
virtual ~GUI();
/**
* Sets up a new frame for ImGui to draw
*/
void beginGUI();
/**
* Ends a frame for ImGui, renders it and draws it onto
* the currently active swapchain image of the core (ready to present).
*/
void endGUI();
};
}
Subproject commit d5828cd988db525f27128edeadb1a689cd2d7461
#include "vkcv/gui/GUI.hpp"
#include <GLFW/glfw3.h>
#include <vkcv/Logger.hpp>
namespace vkcv::gui {
static void checkVulkanResult(VkResult resultCode) {
if (resultCode == 0)
return;
const auto result = vk::Result(resultCode);
vkcv_log(LogLevel::ERROR, "ImGui has a problem with Vulkan! (%s)", vk::to_string(result).c_str());
}
GUI::GUI(Core& core, Window& window) :
m_window(window),
m_core(core),
m_context(m_core.getContext()),
m_gui_context(nullptr) {
IMGUI_CHECKVERSION();
m_gui_context = ImGui::CreateContext();
ImGui_ImplGlfw_InitForVulkan(m_window.getWindow(), false);
f_mouseButton = m_window.e_mouseButton.add([&](int button, int action, int mods) {
ImGui_ImplGlfw_MouseButtonCallback(m_window.getWindow(), button, action, mods);
});
f_mouseScroll = m_window.e_mouseScroll.add([&](double xoffset, double yoffset) {
ImGui_ImplGlfw_ScrollCallback(m_window.getWindow(), xoffset, yoffset);
});
f_key = m_window.e_key.add([&](int key, int scancode, int action, int mods) {
ImGui_ImplGlfw_KeyCallback(m_window.getWindow(), key, scancode, action, mods);
});
f_char = m_window.e_char.add([&](unsigned int c) {
ImGui_ImplGlfw_CharCallback(m_window.getWindow(), c);
});
vk::DescriptorPoolSize pool_sizes[] = {
vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eStorageImage, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eUniformTexelBuffer, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eStorageTexelBuffer, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBufferDynamic, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eStorageBufferDynamic, 1000),
vk::DescriptorPoolSize(vk::DescriptorType::eInputAttachment, 1000)
};
const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo (
vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
static_cast<uint32_t>(1000 * IM_ARRAYSIZE(pool_sizes)),
static_cast<uint32_t>(IM_ARRAYSIZE(pool_sizes)),
pool_sizes
);
m_descriptor_pool = m_context.getDevice().createDescriptorPool(descriptorPoolCreateInfo);
const vk::PhysicalDevice& physicalDevice = m_context.getPhysicalDevice();
const Swapchain& swapchain = m_core.getSwapchain();
const uint32_t graphicsQueueFamilyIndex = (
m_context.getQueueManager().getGraphicsQueues()[0].familyIndex
);
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = m_context.getInstance();
init_info.PhysicalDevice = m_context.getPhysicalDevice();
init_info.Device = m_context.getDevice();
init_info.QueueFamily = graphicsQueueFamilyIndex;
init_info.Queue = m_context.getQueueManager().getGraphicsQueues()[0].handle;
init_info.PipelineCache = nullptr;
init_info.DescriptorPool = m_descriptor_pool;
init_info.Allocator = nullptr;
init_info.MinImageCount = swapchain.getImageCount();
init_info.ImageCount = swapchain.getImageCount();
init_info.CheckVkResultFn = checkVulkanResult;
const vk::AttachmentDescription attachment (
vk::AttachmentDescriptionFlags(),
swapchain.getFormat(),
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eStore,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::ePresentSrcKHR
);
const vk::AttachmentReference attachmentReference (
0,
vk::ImageLayout::eColorAttachmentOptimal
);
const vk::SubpassDescription subpass (
vk::SubpassDescriptionFlags(),
vk::PipelineBindPoint::eGraphics,
0,
nullptr,
1,
&attachmentReference,
nullptr,
nullptr,
0,
nullptr
);
const vk::SubpassDependency dependency (
VK_SUBPASS_EXTERNAL,
0,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlags(),
vk::AccessFlagBits::eColorAttachmentWrite,
vk::DependencyFlags()
);
const vk::RenderPassCreateInfo passCreateInfo (
vk::RenderPassCreateFlags(),
1,
&attachment,
1,
&subpass,
1,
&dependency
);
m_render_pass = m_context.getDevice().createRenderPass(passCreateInfo);
ImGui_ImplVulkan_Init(&init_info, m_render_pass);
const SubmitInfo submitInfo { QueueType::Graphics, {}, {} };
m_core.recordAndSubmitCommands(submitInfo, [](const vk::CommandBuffer& commandBuffer) {
ImGui_ImplVulkan_CreateFontsTexture(commandBuffer);
}, []() {
ImGui_ImplVulkan_DestroyFontUploadObjects();
});
m_context.getDevice().waitIdle();
}
GUI::~GUI() {
m_context.getDevice().waitIdle();
ImGui_ImplVulkan_Shutdown();
m_context.getDevice().destroyRenderPass(m_render_pass);
m_context.getDevice().destroyDescriptorPool(m_descriptor_pool);
ImGui_ImplGlfw_Shutdown();
m_window.e_mouseButton.remove(f_mouseButton);
m_window.e_mouseScroll.remove(f_mouseScroll);
m_window.e_key.remove(f_key);
m_window.e_char.remove(f_char);
if (m_gui_context) {
ImGui::DestroyContext(m_gui_context);
}
}
void GUI::beginGUI() {
const Swapchain& swapchain = m_core.getSwapchain();
const auto extent = swapchain.getExtent();
if ((extent.width > 0) && (extent.height > 0)) {
ImGui_ImplVulkan_SetMinImageCount(swapchain.getImageCount());
}
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
void GUI::endGUI() {
ImGui::Render();
ImDrawData* drawData = ImGui::GetDrawData();
if ((!drawData) ||
(drawData->DisplaySize.x <= 0.0f) ||
(drawData->DisplaySize.y <= 0.0f)) {
return;
}
const Swapchain& swapchain = m_core.getSwapchain();
const auto extent = swapchain.getExtent();
const vk::ImageView swapchainImageView = m_core.getSwapchainImageView();
const vk::FramebufferCreateInfo framebufferCreateInfo (
vk::FramebufferCreateFlags(),
m_render_pass,
1,
&swapchainImageView,
extent.width,
extent.height,
1
);
const vk::Framebuffer framebuffer = m_context.getDevice().createFramebuffer(framebufferCreateInfo);
SubmitInfo submitInfo;
submitInfo.queueType = QueueType::Graphics;
m_core.recordAndSubmitCommands(submitInfo, [&](const vk::CommandBuffer& commandBuffer) {
const vk::Rect2D renderArea (
vk::Offset2D(0, 0),
extent
);
const vk::RenderPassBeginInfo beginInfo (
m_render_pass,
framebuffer,
renderArea,
0,
nullptr
);
commandBuffer.beginRenderPass(beginInfo, vk::SubpassContents::eInline);
ImGui_ImplVulkan_RenderDrawData(drawData, commandBuffer);
commandBuffer.endRenderPass();
}, [&]() {
m_context.getDevice().destroyFramebuffer(framebuffer);
});
}
}
#include <iostream>
#include <vkcv/Core.hpp>
#include <GLFW/glfw3.h>
#include <vkcv/camera/CameraManager.hpp>
#include <chrono>
#include <vkcv/asset/asset_loader.hpp>
int main(int argc, const char** argv) {
const char* applicationName = "First Mesh";
uint32_t windowWidth = 800;
uint32_t windowHeight = 600;
vkcv::Window window = vkcv::Window::create(
applicationName,
windowWidth,
windowHeight,
true
);
vkcv::camera::CameraManager cameraManager(window);
uint32_t camIndex = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
uint32_t camIndex2 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL);
cameraManager.getCamera(camIndex).setPosition(glm::vec3(0.f, 0.f, 3.f));
cameraManager.getCamera(camIndex).setNearFar(0.1f, 30.0f);
cameraManager.getCamera(camIndex).setYaw(180.0f);
cameraManager.getCamera(camIndex2).setNearFar(0.1f, 30.0f);
window.initEvents();
vkcv::Core core = vkcv::Core::create(
window,
applicationName,
VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
{},
{ "VK_KHR_swapchain" }
);
vkcv::asset::Scene mesh;
const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
int result = vkcv::asset::loadScene(path, mesh);
if (result == 1) {
std::cout << "Mesh loading successful!" << std::endl;
}
else {
std::cout << "Mesh loading failed: " << result << std::endl;
return 1;
}
assert(mesh.vertexGroups.size() > 0);
auto vertexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::VERTEX,
mesh.vertexGroups[0].vertexBuffer.data.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL
);
vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
auto indexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::INDEX,
mesh.vertexGroups[0].indexBuffer.data.size(),
vkcv::BufferMemoryType::DEVICE_LOCAL
);
indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
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(attributes[0].offset, vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(attributes[1].offset, vertexBuffer.getVulkanHandle()),
vkcv::VertexBufferBinding(attributes[2].offset, vertexBuffer.getVulkanHandle()) };
const vkcv::Mesh loadedMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
// an example attachment for passes that output to the window
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,
vk::Format::eD32Sfloat
);
vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment });
vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
if (!firstMeshPass) {
std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
return EXIT_FAILURE;
}
vkcv::ShaderProgram firstMeshProgram{};
firstMeshProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/vert.spv"));
firstMeshProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv"));
const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.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 firstMeshLayout (bindings);
std::vector<vkcv::DescriptorBinding> descriptorBindings = { firstMeshProgram.getReflectedDescriptors()[0] };
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
const vkcv::PipelineConfig firstMeshPipelineConfig {
firstMeshProgram,
windowWidth,
windowHeight,
firstMeshPass,
firstMeshLayout,
{ core.getDescriptorSet(descriptorSet).layout },
true
};
vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
if (!firstMeshPipeline) {
std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
return EXIT_FAILURE;
}
//vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, mesh.texture_hack.w, mesh.texture_hack.h);
//texture.fill(mesh.texture_hack.img);
vkcv::asset::Texture &tex = mesh.textures[0];
vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
texture.fill(tex.data.data());
vkcv::SamplerHandle sampler = core.createSampler(
vkcv::SamplerFilterType::LINEAR,
vkcv::SamplerFilterType::LINEAR,
vkcv::SamplerMipmapMode::LINEAR,
vkcv::SamplerAddressMode::REPEAT
);
vkcv::SamplerHandle shadowSampler = core.createSampler(
vkcv::SamplerFilterType::NEAREST,
vkcv::SamplerFilterType::NEAREST,
vkcv::SamplerMipmapMode::NEAREST,
vkcv::SamplerAddressMode::CLAMP_TO_EDGE
);
vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
const std::vector<glm::vec3> instancePositions = {
glm::vec3( 0.f, -2.f, 0.f),
glm::vec3( 3.f, 0.f, 0.f),
glm::vec3(-3.f, 0.f, 0.f),
glm::vec3( 0.f, 2.f, 0.f),
glm::vec3( 0.f, -5.f, 0.f)
};
std::vector<glm::mat4> modelMatrices;
std::vector<vkcv::DrawcallInfo> drawcalls;
std::vector<vkcv::DrawcallInfo> shadowDrawcalls;
for (const auto& position : instancePositions) {
modelMatrices.push_back(glm::translate(glm::mat4(1.f), position));
drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage }));
shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {}));
}
modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f));
std::vector<std::array<glm::mat4, 2>> mainPassMatrices;
std::vector<glm::mat4> mvpLight;
vkcv::ShaderProgram shadowShader;
shadowShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow_vert.spv");
shadowShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow_frag.spv");
const vk::Format shadowMapFormat = vk::Format::eD16Unorm;
const std::vector<vkcv::AttachmentDescription> shadowAttachments = {
vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat)
};
const vkcv::PassConfig shadowPassConfig(shadowAttachments);
const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig);
const uint32_t shadowMapResolution = 1024;
const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1);
const vkcv::PipelineConfig shadowPipeConfig {
shadowShader,
shadowMapResolution,
shadowMapResolution,
shadowPass,
firstMeshLayout,
{},
false
};
const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig);
struct LightInfo {
glm::vec3 direction;
float padding;
glm::mat4 lightMatrix;
};
LightInfo lightInfo;
vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3));
vkcv::DescriptorWrites setWrites;
setWrites.sampledImageWrites = {
vkcv::SampledImageDescriptorWrite(0, texture.getHandle()),
vkcv::SampledImageDescriptorWrite(3, shadowMap.getHandle()) };
setWrites.samplerWrites = {
vkcv::SamplerDescriptorWrite(1, sampler),
vkcv::SamplerDescriptorWrite(4, shadowSampler) };
setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) };
core.writeDescriptorSet(descriptorSet, setWrites);
auto start = std::chrono::system_clock::now();
const auto appStartTime = start;
while (window.isWindowOpen()) {
vkcv::Window::pollEvents();
uint32_t swapchainWidth, swapchainHeight;
if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
continue;
}
if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) {
depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
windowWidth = swapchainWidth;
windowHeight = swapchainHeight;
}
auto end = std::chrono::system_clock::now();
auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
start = end;
cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - appStartTime);
const float sunTheta = 0.001f * static_cast<float>(duration.count());
lightInfo.direction = glm::normalize(glm::vec3(std::cos(sunTheta), 1, std::sin(sunTheta)));
const float shadowProjectionSize = 5.f;
glm::mat4 projectionLight = glm::ortho(
-shadowProjectionSize,
shadowProjectionSize,
-shadowProjectionSize,
shadowProjectionSize,
-shadowProjectionSize,
shadowProjectionSize);
glm::mat4 vulkanCorrectionMatrix(1.f);
vulkanCorrectionMatrix[2][2] = 0.5;
vulkanCorrectionMatrix[3][2] = 0.5;
projectionLight = vulkanCorrectionMatrix * projectionLight;
const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), -lightInfo.direction, glm::vec3(0, -1, 0));
lightInfo.lightMatrix = projectionLight * viewLight;
lightBuffer.fill({ lightInfo });
const glm::mat4 viewProjectionCamera = cameraManager.getActiveCamera().getMVP();
mainPassMatrices.clear();
mvpLight.clear();
for (const auto& m : modelMatrices) {
mainPassMatrices.push_back({ viewProjectionCamera * m, m });
mvpLight.push_back(lightInfo.lightMatrix* m);
}
vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4));
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4));
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
core.recordDrawcallsToCmdStream(
cmdStream,
shadowPass,
shadowPipe,
shadowPushConstantData,
shadowDrawcalls,
{ shadowMap.getHandle() });
core.prepareImageForSampling(cmdStream, shadowMap.getHandle());
core.recordDrawcallsToCmdStream(
cmdStream,
firstMeshPass,
firstMeshPipeline,
pushConstantData,
drawcalls,
renderTargets);
core.prepareSwapchainImageForPresent(cmdStream);
core.submitCommandStream(cmdStream);
core.endFrame();
}
return 0;
}
......@@ -63,7 +63,7 @@ int main(int argc, const char** argv) {
const vkcv::AttachmentDescription present_color_attachment(
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
core.getSwapchainImageFormat()
core.getSwapchain().getFormat()
);
const vkcv::AttachmentDescription depth_attachment(
......
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