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
Commits on Source (17)
Showing
with 405 additions and 258 deletions
...@@ -50,10 +50,7 @@ set(vkcv_sources ...@@ -50,10 +50,7 @@ set(vkcv_sources
${vkcv_include}/vkcv/QueueManager.hpp ${vkcv_include}/vkcv/QueueManager.hpp
${vkcv_source}/vkcv/QueueManager.cpp ${vkcv_source}/vkcv/QueueManager.cpp
${vkcv_source}/vkcv/Surface.hpp
${vkcv_source}/vkcv/Surface.cpp
${vkcv_source}/vkcv/ImageLayoutTransitions.hpp ${vkcv_source}/vkcv/ImageLayoutTransitions.hpp
${vkcv_source}/vkcv/ImageLayoutTransitions.cpp ${vkcv_source}/vkcv/ImageLayoutTransitions.cpp
......
...@@ -56,13 +56,12 @@ namespace vkcv ...@@ -56,13 +56,12 @@ namespace vkcv
* *
* @param context encapsulates various Vulkan objects * @param context encapsulates various Vulkan objects
*/ */
Core(Context &&context, Window &window, 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; const CommandResources& commandResources, const SyncResources& syncResources) noexcept;
// explicit destruction of default constructor // explicit destruction of default constructor
Core() = delete; Core() = delete;
Result acquireSwapchainImage(); Result acquireSwapchainImage();
void destroyTemporaryFramebuffers();
Context m_Context; Context m_Context;
...@@ -80,16 +79,12 @@ namespace vkcv ...@@ -80,16 +79,12 @@ namespace vkcv
CommandResources m_CommandResources; CommandResources m_CommandResources;
SyncResources m_SyncResources; SyncResources m_SyncResources;
uint32_t m_currentSwapchainImageIndex; uint32_t m_currentSwapchainImageIndex;
std::vector<vk::Framebuffer> m_TemporaryFramebuffers;
ImageHandle m_DepthImage; ImageHandle m_DepthImage;
/** std::function<void(int, int)> e_resizeHandle;
* recreates the swapchain
* @param[in] width new window width static std::vector<vk::ImageView> createImageViews( Context &context, SwapChain& swapChain);
* @param[in] height new window hight
*/
static void recreateSwapchain(int width, int height);
public: public:
/** /**
...@@ -230,14 +225,12 @@ namespace vkcv ...@@ -230,14 +225,12 @@ namespace vkcv
* @brief render a beautiful triangle * @brief render a beautiful triangle
*/ */
void renderMesh( void renderMesh(
const PassHandle renderpassHandle, const PassHandle &renderpassHandle,
const PipelineHandle pipelineHandle, const PipelineHandle &pipelineHandle,
const uint32_t width,
const uint32_t height,
const size_t pushConstantSize, const size_t pushConstantSize,
const void* pushConstantData, const void* pushConstantData,
const std::vector<VertexBufferBinding> &vertexBufferBindings, const std::vector<VertexBufferBinding> &vertexBufferBindings,
const BufferHandle indexBuffer, const BufferHandle &indexBuffer,
const size_t indexCount, const size_t indexCount,
const vkcv::ResourcesHandle resourceHandle, const vkcv::ResourcesHandle resourceHandle,
const size_t resourceDescriptorSetIndex); const size_t resourceDescriptorSetIndex);
......
...@@ -3,15 +3,32 @@ ...@@ -3,15 +3,32 @@
#include "Context.hpp" #include "Context.hpp"
#include "vkcv/Window.hpp" #include "vkcv/Window.hpp"
namespace vkcv { #include <atomic>
namespace vkcv
{
class SwapChain final { class SwapChain final {
private: private:
vk::SurfaceKHR m_surface; struct Surface
vk::SwapchainKHR m_swapchain; {
vk::SurfaceFormatKHR m_format; vk::SurfaceKHR handle;
std::vector<vk::SurfaceFormatKHR> formats;
vk::SurfaceCapabilitiesKHR capabilities;
std::vector<vk::PresentModeKHR> presentModes;
};
Surface m_Surface;
uint32_t m_ImageCount; vk::SwapchainKHR m_Swapchain;
vk::Format m_SwapchainFormat;
vk::ColorSpaceKHR m_SwapchainColorSpace;
vk::PresentModeKHR m_SwapchainPresentMode;
uint32_t m_SwapchainImageCount;
vk::Extent2D m_Extent;
std::atomic<bool> m_RecreationRequired;
/** /**
* Constructor of a SwapChain object * Constructor of a SwapChain object
...@@ -21,11 +38,17 @@ namespace vkcv { ...@@ -21,11 +38,17 @@ namespace vkcv {
* @param swapchain to show images in the window * @param swapchain to show images in the window
* @param format * @param format
*/ */
SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount); // TODO:
SwapChain(const Surface &surface,
vk::SwapchainKHR swapchain,
vk::Format format,
vk::ColorSpaceKHR colorSpace,
vk::PresentModeKHR presentMode,
uint32_t imageCount,
vk::Extent2D extent) noexcept;
public: public:
SwapChain(const SwapChain &other) = default; SwapChain(const SwapChain& other);
SwapChain(SwapChain &&other) = default;
/** /**
* @return The swapchain linked with the #SwapChain class * @return The swapchain linked with the #SwapChain class
...@@ -39,13 +62,14 @@ namespace vkcv { ...@@ -39,13 +62,14 @@ namespace vkcv {
* @return current surface * @return current surface
*/ */
[[nodiscard]] [[nodiscard]]
vk::SurfaceKHR getSurface(); vk::SurfaceKHR getSurface() const;
/** /**
* gets the current surface format * gets the chosen swapchain format
* @return gets the surface format * @return gets the chosen swapchain format
*/ */
[[nodiscard]] [[nodiscard]]
vk::SurfaceFormatKHR getSurfaceFormat(); vk::Format getSwapchainFormat() const;
/** /**
* creates a swap chain object out of the given window and the given context * creates a swap chain object out of the given window and the given context
...@@ -53,7 +77,7 @@ namespace vkcv { ...@@ -53,7 +77,7 @@ namespace vkcv {
* @param context of the application * @param context of the application
* @return returns an object of swapChain * @return returns an object of swapChain
*/ */
static SwapChain create(const Window &window, const Context &context, const vk::SurfaceKHR surface); static SwapChain create(const Window &window, const Context &context);
/** /**
* Destructor of SwapChain * Destructor of SwapChain
...@@ -64,6 +88,34 @@ namespace vkcv { ...@@ -64,6 +88,34 @@ namespace vkcv {
* @return number of images in swapchain * @return number of images in swapchain
*/ */
uint32_t getImageCount(); uint32_t getImageCount();
};
/**
* TODO
*
* @return
*/
bool shouldUpdateSwapchain() const;
/**
* TODO
*
* context
* window
*/
void updateSwapchain(const Context &context, const Window &window);
/**
*
*/
void recreateSwapchain();
/**
* TODO
*
* @return
*/
[[nodiscard]]
const vk::Extent2D& getExtent() const;
};
} }
...@@ -17,7 +17,6 @@ namespace vkcv { ...@@ -17,7 +17,6 @@ namespace vkcv {
private: private:
GLFWwindow *m_window; GLFWwindow *m_window;
/** /**
* *
* @param GLFWwindow of the class * @param GLFWwindow of the class
......
...@@ -63,7 +63,7 @@ namespace vkcv { ...@@ -63,7 +63,7 @@ namespace vkcv {
void changeFov(double fov); void changeFov(double fov);
void updateRatio(float ratio); void updateRatio(int width, int height);
float getRatio() const; float getRatio() const;
......
...@@ -9,10 +9,11 @@ namespace vkcv{ ...@@ -9,10 +9,11 @@ namespace vkcv{
class CameraManager{ class CameraManager{
private: private:
std::function<void(int, int, int, int)> m_keyHandle; std::function<void(int, int, int, int)> e_keyHandle;
std::function<void(double, double)> m_mouseMoveHandle; std::function<void(double, double)> e_mouseMoveHandle;
std::function<void(double, double)> m_mouseScrollHandle; std::function<void(double, double)> e_mouseScrollHandle;
std::function<void(int, int, int)> m_mouseButtonHandle; std::function<void(int, int, int)> e_mouseButtonHandle;
std::function<void(int, int)> e_resizeHandle;
Window &m_window; Window &m_window;
Camera m_camera; Camera m_camera;
...@@ -29,6 +30,7 @@ namespace vkcv{ ...@@ -29,6 +30,7 @@ namespace vkcv{
void scrollCallback( double offsetX, double offsetY); void scrollCallback( double offsetX, double offsetY);
void mouseMoveCallback( double offsetX, double offsetY); void mouseMoveCallback( double offsetX, double offsetY);
void mouseButtonCallback(int button, int action, int mods); void mouseButtonCallback(int button, int action, int mods);
void resizeCallback(int width, int height);
public: public:
CameraManager(Window &window, float width, float height, glm::vec3 up = glm::vec3(0.0f,-1.0f,0.0f), glm::vec3 position = glm::vec3(0.0f,0.0f,0.0f)); CameraManager(Window &window, float width, float height, glm::vec3 up = glm::vec3(0.0f,-1.0f,0.0f), glm::vec3 position = glm::vec3(0.0f,0.0f,0.0f));
......
...@@ -82,8 +82,10 @@ namespace vkcv { ...@@ -82,8 +82,10 @@ namespace vkcv {
setFov(fov); setFov(fov);
} }
void Camera::updateRatio( float ratio){ void Camera::updateRatio( int width, int height){
m_ratio = ratio; m_width = width;
m_height = height;
m_ratio = static_cast<float>(width)/glm::max(height, 1);
setPerspective( m_fov, m_ratio, m_near, m_far); setPerspective( m_fov, m_ratio, m_near, m_far);
} }
......
...@@ -15,10 +15,11 @@ namespace vkcv{ ...@@ -15,10 +15,11 @@ namespace vkcv{
} }
void CameraManager::bindCamera(){ void CameraManager::bindCamera(){
m_keyHandle = m_window.e_key.add( [&](int key, int scancode, int action, int mods) { this->keyCallback(key, scancode, action, mods); }); e_keyHandle = m_window.e_key.add( [&](int key, int scancode, int action, int mods) { this->keyCallback(key, scancode, action, mods); });
m_mouseMoveHandle = m_window.e_mouseMove.add( [&]( double offsetX, double offsetY) {this->mouseMoveCallback( offsetX, offsetY);} ); e_mouseMoveHandle = m_window.e_mouseMove.add( [&]( double offsetX, double offsetY) {this->mouseMoveCallback( offsetX, offsetY);} );
m_mouseScrollHandle = m_window.e_mouseScroll.add([&](double offsetX, double offsetY) {this->scrollCallback( offsetX, offsetY);} ); e_mouseScrollHandle = m_window.e_mouseScroll.add([&](double offsetX, double offsetY) {this->scrollCallback( offsetX, offsetY);} );
m_mouseButtonHandle = m_window.e_mouseButton.add([&] (int button, int action, int mods) {this->mouseButtonCallback( button, action, mods);}); e_mouseButtonHandle = m_window.e_mouseButton.add([&] (int button, int action, int mods) {this->mouseButtonCallback( button, action, mods);});
e_resizeHandle = m_window.e_resize.add([&] (int width, int height) {this->resizeCallback( width, height);});
} }
void CameraManager::mouseButtonCallback(int button, int action, int mods){ void CameraManager::mouseButtonCallback(int button, int action, int mods){
...@@ -75,6 +76,11 @@ namespace vkcv{ ...@@ -75,6 +76,11 @@ namespace vkcv{
break; break;
} }
} }
void CameraManager::resizeCallback(int width, int height){
m_camera.updateRatio(width, height);
}
Camera &CameraManager::getCamera(){ Camera &CameraManager::getCamera(){
return m_camera; return m_camera;
} }
......
...@@ -8,16 +8,14 @@ ...@@ -8,16 +8,14 @@
int main(int argc, const char** argv) { int main(int argc, const char** argv) {
const char* applicationName = "First Mesh"; const char* applicationName = "First Mesh";
const int windowWidth = 800;
const int windowHeight = 600;
vkcv::Window window = vkcv::Window::create( vkcv::Window window = vkcv::Window::create(
applicationName, applicationName,
windowWidth, 800,
windowHeight, 600,
false true
); );
vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); vkcv::CameraManager cameraManager(window, static_cast<float>(window.getWidth()), static_cast<float>(window.getHeight()));
window.initEvents(); window.initEvents();
...@@ -43,7 +41,7 @@ int main(int argc, const char** argv) { ...@@ -43,7 +41,7 @@ int main(int argc, const char** argv) {
return 1; return 1;
} }
assert(mesh.vertexGroups.size() > 0); assert(!mesh.vertexGroups.empty());
auto vertexBuffer = core.createBuffer<uint8_t>( auto vertexBuffer = core.createBuffer<uint8_t>(
vkcv::BufferType::VERTEX, vkcv::BufferType::VERTEX,
mesh.vertexGroups[0].vertexBuffer.data.size(), mesh.vertexGroups[0].vertexBuffer.data.size(),
...@@ -112,9 +110,9 @@ int main(int argc, const char** argv) { ...@@ -112,9 +110,9 @@ int main(int argc, const char** argv) {
//end of exemplary code //end of exemplary code
const vkcv::PipelineConfig trianglePipelineDefinition( const vkcv::PipelineConfig trianglePipelineDefinition(
triangleShaderProgram, triangleShaderProgram,
windowWidth, UINT32_MAX,
windowHeight, UINT32_MAX,
trianglePass, trianglePass,
mesh.vertexGroups[0].vertexBuffer.attributes, mesh.vertexGroups[0].vertexBuffer.attributes,
{ core.getDescriptorSetLayout(set, 0) }); { core.getDescriptorSetLayout(set, 0) });
...@@ -148,8 +146,12 @@ int main(int argc, const char** argv) { ...@@ -148,8 +146,12 @@ int main(int argc, const char** argv) {
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
while (window.isWindowOpen()) { while (window.isWindowOpen()) {
vkcv::Window::pollEvents();
if(window.getHeight() == 0 || window.getWidth() == 0)
continue;
core.beginFrame(); core.beginFrame();
window.pollEvents();
auto end = std::chrono::system_clock::now(); auto end = std::chrono::system_clock::now();
auto deltatime = end - start; auto deltatime = end - start;
start = end; start = end;
...@@ -159,8 +161,6 @@ int main(int argc, const char** argv) { ...@@ -159,8 +161,6 @@ int main(int argc, const char** argv) {
core.renderMesh( core.renderMesh(
trianglePass, trianglePass,
trianglePipeline, trianglePipeline,
windowWidth,
windowHeight,
sizeof(mvp), sizeof(mvp),
&mvp, &mvp,
vertexBufferBindings, vertexBufferBindings,
......
...@@ -147,8 +147,6 @@ int main(int argc, const char** argv) { ...@@ -147,8 +147,6 @@ int main(int argc, const char** argv) {
core.renderMesh( core.renderMesh(
trianglePass, trianglePass,
trianglePipeline, trianglePipeline,
windowWidth,
windowHeight,
sizeof(mvp), sizeof(mvp),
&mvp, &mvp,
vertexBufferBindings, vertexBufferBindings,
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "SamplerManager.hpp" #include "SamplerManager.hpp"
#include "ImageManager.hpp" #include "ImageManager.hpp"
#include "DescriptorManager.hpp" #include "DescriptorManager.hpp"
#include "Surface.hpp"
#include "ImageLayoutTransitions.hpp" #include "ImageLayoutTransitions.hpp"
namespace vkcv namespace vkcv
...@@ -32,40 +31,11 @@ namespace vkcv ...@@ -32,40 +31,11 @@ namespace vkcv
instanceExtensions, instanceExtensions,
deviceExtensions deviceExtensions
); );
const vk::SurfaceKHR surface = createSurface(
window.getWindow(),
context.getInstance(),
context.getPhysicalDevice()
);
SwapChain swapChain = SwapChain::create(window, context, surface); SwapChain swapChain = SwapChain::create(window, context);
std::vector<vk::Image> swapChainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain());
std::vector<vk::ImageView> imageViews; std::vector<vk::ImageView> imageViews;
imageViews.reserve( swapChainImages.size() ); imageViews = createImageViews( context, swapChain);
//here can be swizzled with vk::ComponentSwizzle if needed
vk::ComponentMapping componentMapping(
vk::ComponentSwizzle::eR,
vk::ComponentSwizzle::eG,
vk::ComponentSwizzle::eB,
vk::ComponentSwizzle::eA );
vk::ImageSubresourceRange subResourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 );
for ( auto image : swapChainImages )
{
vk::ImageViewCreateInfo imageViewCreateInfo(
vk::ImageViewCreateFlags(),
image,
vk::ImageViewType::e2D,
swapChain.getSurfaceFormat().format,
componentMapping,
subResourceRange
);
imageViews.push_back(context.getDevice().createImageView(imageViewCreateInfo));
}
const auto& queueManager = context.getQueueManager(); const auto& queueManager = context.getQueueManager();
...@@ -74,10 +44,6 @@ namespace vkcv ...@@ -74,10 +44,6 @@ namespace vkcv
const auto commandResources = createCommandResources(context.getDevice(), queueFamilySet); const auto commandResources = createCommandResources(context.getDevice(), queueFamilySet);
const auto defaultSyncResources = createSyncResources(context.getDevice()); const auto defaultSyncResources = createSyncResources(context.getDevice());
window.e_resize.add([&](int width, int height){
recreateSwapchain(width,height);
});
return Core(std::move(context) , window, swapChain, imageViews, commandResources, defaultSyncResources); return Core(std::move(context) , window, swapChain, imageViews, commandResources, defaultSyncResources);
} }
...@@ -86,7 +52,7 @@ namespace vkcv ...@@ -86,7 +52,7 @@ namespace vkcv
return m_Context; return m_Context;
} }
Core::Core(Context &&context, Window &window , SwapChain swapChain, std::vector<vk::ImageView> imageViews, Core::Core(Context &&context, Window &window, const SwapChain& swapChain, std::vector<vk::ImageView> imageViews,
const CommandResources& commandResources, const SyncResources& syncResources) noexcept : const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
m_Context(std::move(context)), m_Context(std::move(context)),
m_window(window), m_window(window),
...@@ -105,6 +71,10 @@ namespace vkcv ...@@ -105,6 +71,10 @@ namespace vkcv
m_BufferManager->init(); m_BufferManager->init();
m_ImageManager->m_core = this; m_ImageManager->m_core = this;
e_resizeHandle = window.e_resize.add( [&](int width, int height) {
m_swapchain.recreateSwapchain();
});
} }
Core::~Core() noexcept { Core::~Core() noexcept {
...@@ -115,7 +85,6 @@ namespace vkcv ...@@ -115,7 +85,6 @@ namespace vkcv
destroyCommandResources(m_Context.getDevice(), m_CommandResources); destroyCommandResources(m_Context.getDevice(), m_CommandResources);
destroySyncResources(m_Context.getDevice(), m_SyncResources); destroySyncResources(m_Context.getDevice(), m_SyncResources);
destroyTemporaryFramebuffers();
m_Context.m_Device.destroySwapchainKHR(m_swapchain.getSwapchain()); m_Context.m_Device.destroySwapchainKHR(m_swapchain.getSwapchain());
m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface()); m_Context.m_Instance.destroySurfaceKHR(m_swapchain.getSurface());
...@@ -144,6 +113,7 @@ namespace vkcv ...@@ -144,6 +113,7 @@ namespace vkcv
); );
if (acquireResult != vk::Result::eSuccess) { if (acquireResult != vk::Result::eSuccess) {
std::cerr << vk::to_string(acquireResult) << std::endl;
return Result::ERROR; return Result::ERROR;
} }
...@@ -151,37 +121,33 @@ namespace vkcv ...@@ -151,37 +121,33 @@ namespace vkcv
return Result::SUCCESS; return Result::SUCCESS;
} }
void Core::destroyTemporaryFramebuffers() {
for (const vk::Framebuffer f : m_TemporaryFramebuffers) {
m_Context.getDevice().destroyFramebuffer(f);
}
m_TemporaryFramebuffers.clear();
}
void Core::beginFrame() { void Core::beginFrame() {
if (m_swapchain.shouldUpdateSwapchain()) {
m_Context.getDevice().waitIdle();
for (auto image : m_swapchainImageViews)
m_Context.m_Device.destroyImageView(image);
m_swapchain.updateSwapchain(m_Context, m_window);
m_swapchainImageViews = createImageViews(m_Context, m_swapchain);
}
if (acquireSwapchainImage() != Result::SUCCESS) { if (acquireSwapchainImage() != Result::SUCCESS) {
return; std::cerr << "Acquire failed!" << std::endl;
m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max();
} }
m_Context.getDevice().waitIdle(); // FIMXE: this is a sin against graphics programming, but its getting late - Alex
destroyTemporaryFramebuffers(); m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but its getting late - Alex
}
vk::Framebuffer createFramebuffer(const vk::Device device, const vk::RenderPass& renderpass,
const int width, const int height, const std::vector<vk::ImageView>& attachments) {
const vk::FramebufferCreateFlags flags = {};
const vk::FramebufferCreateInfo createInfo(flags, renderpass, attachments.size(), attachments.data(), width, height, 1);
return device.createFramebuffer(createInfo);
} }
void Core::renderMesh( void Core::renderMesh(
const PassHandle renderpassHandle, const PassHandle &renderpassHandle,
const PipelineHandle pipelineHandle, const PipelineHandle &pipelineHandle,
const uint32_t width, const size_t pushConstantSize,
const uint32_t height,
const size_t pushConstantSize,
const void *pushConstantData, const void *pushConstantData,
const std::vector<VertexBufferBinding>& vertexBufferBindings, const std::vector<VertexBufferBinding>& vertexBufferBindings,
const BufferHandle indexBuffer, const BufferHandle &indexBuffer,
const size_t indexCount, const size_t indexCount,
const vkcv::ResourcesHandle resourceHandle, const vkcv::ResourcesHandle resourceHandle,
const size_t resourceDescriptorSetIndex const size_t resourceDescriptorSetIndex
...@@ -190,6 +156,11 @@ namespace vkcv ...@@ -190,6 +156,11 @@ namespace vkcv
if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
return; return;
} }
const vk::Extent2D& extent = m_swapchain.getExtent();
const uint32_t width = extent.width;
const uint32_t height = extent.height;
const vk::RenderPass renderpass = m_PassManager->getVkPass(renderpassHandle); const vk::RenderPass renderpass = m_PassManager->getVkPass(renderpassHandle);
const PassConfig passConfig = m_PassManager->getPassConfig(renderpassHandle); const PassConfig passConfig = m_PassManager->getPassConfig(renderpassHandle);
...@@ -212,6 +183,7 @@ namespace vkcv ...@@ -212,6 +183,7 @@ namespace vkcv
const vk::ImageView imageView = m_swapchainImageViews[m_currentSwapchainImageIndex]; const vk::ImageView imageView = m_swapchainImageViews[m_currentSwapchainImageIndex];
const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle); const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle);
const vk::PipelineLayout pipelineLayout = m_PipelineManager->getVkPipelineLayout(pipelineHandle); const vk::PipelineLayout pipelineLayout = m_PipelineManager->getVkPipelineLayout(pipelineHandle);
const vkcv::PipelineConfig pipelineConfig = m_PipelineManager->getPipelineConfig(pipelineHandle);
const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height)); const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height));
const vk::Buffer vulkanIndexBuffer = m_BufferManager->getBuffer(indexBuffer); const vk::Buffer vulkanIndexBuffer = m_BufferManager->getBuffer(indexBuffer);
...@@ -222,15 +194,25 @@ namespace vkcv ...@@ -222,15 +194,25 @@ namespace vkcv
attachments.push_back(m_ImageManager->getVulkanImageView(m_DepthImage)); attachments.push_back(m_ImageManager->getVulkanImageView(m_DepthImage));
} }
const vk::Framebuffer framebuffer = createFramebuffer( vk::Framebuffer framebuffer = nullptr;
m_Context.getDevice(), const vk::FramebufferCreateInfo createInfo({},
renderpass, renderpass,
width, static_cast<uint32_t>(attachments.size()),
height, attachments.data(),
attachments width,
); height,
1);
m_TemporaryFramebuffers.push_back(framebuffer); if(m_Context.m_Device.createFramebuffer(&createInfo, nullptr, &framebuffer) != vk::Result::eSuccess)
{
std::cout << "FAILED TO CREATE TEMPORARY FRAMEBUFFER!" << std::endl;
return;
}
vk::Viewport dynamicViewport(0.0f, 0.0f,
static_cast<float>(width), static_cast<float>(height),
0.0f, 1.0f);
vk::Rect2D dynamicScissor({0, 0}, {width, height});
auto &bufferManager = m_BufferManager; auto &bufferManager = m_BufferManager;
...@@ -238,48 +220,61 @@ namespace vkcv ...@@ -238,48 +220,61 @@ namespace vkcv
submitInfo.queueType = QueueType::Graphics; submitInfo.queueType = QueueType::Graphics;
submitInfo.signalSemaphores = { m_SyncResources.renderFinished }; submitInfo.signalSemaphores = { m_SyncResources.renderFinished };
submitCommands(submitInfo, [&](const vk::CommandBuffer& cmdBuffer) { auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
std::vector<vk::ClearValue> clearValues; std::vector<vk::ClearValue> clearValues;
for (const auto& attachment : passConfig.attachments) { for (const auto& attachment : passConfig.attachments) {
if (attachment.load_operation == AttachmentOperation::CLEAR) { if (attachment.load_operation == AttachmentOperation::CLEAR) {
float clear = 0.0f; float clear = 0.0f;
if (attachment.layout_final == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) { if (attachment.layout_final == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT) {
clear = 1.0f; clear = 1.0f;
} }
clearValues.emplace_back(std::array<float, 4>{ clearValues.emplace_back(std::array<float, 4>{
clear, clear,
clear, clear,
clear, clear,
1.f 1.f
}); });
} }
} }
const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data()); const vk::RenderPassBeginInfo beginInfo(renderpass, framebuffer, renderArea, clearValues.size(), clearValues.data());
const vk::SubpassContents subpassContents = {}; const vk::SubpassContents subpassContents = {};
cmdBuffer.beginRenderPass(beginInfo, subpassContents, {}); cmdBuffer.beginRenderPass(beginInfo, subpassContents, {});
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
if(pipelineConfig.m_Height == UINT32_MAX && pipelineConfig.m_Width == UINT32_MAX)
{
cmdBuffer.setViewport(0, 1, &dynamicViewport);
cmdBuffer.setScissor(0, 1, &dynamicScissor);
}
for (uint32_t i = 0; i < vertexBufferBindings.size(); i++) {
const auto &vertexBinding = vertexBufferBindings[i];
const auto vertexBuffer = bufferManager->getBuffer(vertexBinding.buffer);
cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset));
}
if (resourceHandle) {
const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex);
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr);
}
cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size
cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData);
cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {});
cmdBuffer.endRenderPass();
};
auto finishFunction = [&]()
{
m_Context.m_Device.destroy(framebuffer);
};
for (uint32_t i = 0; i < vertexBufferBindings.size(); i++) { submitCommands(submitInfo, submitFunction, finishFunction);
const auto &vertexBinding = vertexBufferBindings[i];
const auto vertexBuffer = bufferManager->getBuffer(vertexBinding.buffer);
cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset));
}
if (resourceHandle) {
const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex);
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr);
}
cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size
cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData);
cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {});
cmdBuffer.endRenderPass();
}, nullptr);
} }
void Core::endFrame() { void Core::endFrame() {
...@@ -288,8 +283,7 @@ namespace vkcv ...@@ -288,8 +283,7 @@ namespace vkcv
} }
const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain()); const auto swapchainImages = m_Context.getDevice().getSwapchainImagesKHR(m_swapchain.getSwapchain());
const vk::Image presentImage = swapchainImages[m_currentSwapchainImageIndex];
const auto& queueManager = m_Context.getQueueManager(); const auto& queueManager = m_Context.getQueueManager();
std::array<vk::Semaphore, 2> waitSemaphores{ std::array<vk::Semaphore, 2> waitSemaphores{
m_SyncResources.renderFinished, m_SyncResources.renderFinished,
...@@ -309,13 +303,8 @@ namespace vkcv ...@@ -309,13 +303,8 @@ namespace vkcv
} }
vk::Format Core::getSwapchainImageFormat() { vk::Format Core::getSwapchainImageFormat() {
return m_swapchain.getSurfaceFormat().format; return m_swapchain.getSwapchainFormat();
} }
void Core::recreateSwapchain(int width, int height) {
/* boilerplate for #34 */
std::cout << "Resized to : " << width << " , " << height << std::endl;
}
void Core::submitCommands(const SubmitInfo &submitInfo, const RecordCommandFunction& record, const FinishCommandFunction& finish) void Core::submitCommands(const SubmitInfo &submitInfo, const RecordCommandFunction& record, const FinishCommandFunction& finish)
{ {
...@@ -369,4 +358,33 @@ namespace vkcv ...@@ -369,4 +358,33 @@ namespace vkcv
vk::DescriptorSetLayout Core::getDescriptorSetLayout(ResourcesHandle handle, size_t setIndex) { vk::DescriptorSetLayout Core::getDescriptorSetLayout(ResourcesHandle handle, size_t setIndex) {
return m_DescriptorManager->getDescriptorSetLayout(handle, setIndex); return m_DescriptorManager->getDescriptorSetLayout(handle, setIndex);
} }
std::vector<vk::ImageView> Core::createImageViews( Context &context, SwapChain& swapChain){
std::vector<vk::ImageView> imageViews;
std::vector<vk::Image> swapChainImages = context.getDevice().getSwapchainImagesKHR(swapChain.getSwapchain());
imageViews.reserve( swapChainImages.size() );
//here can be swizzled with vk::ComponentSwizzle if needed
vk::ComponentMapping componentMapping(
vk::ComponentSwizzle::eR,
vk::ComponentSwizzle::eG,
vk::ComponentSwizzle::eB,
vk::ComponentSwizzle::eA );
vk::ImageSubresourceRange subResourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 );
for ( auto image : swapChainImages )
{
vk::ImageViewCreateInfo imageViewCreateInfo(
vk::ImageViewCreateFlags(),
image,
vk::ImageViewType::e2D,
swapChain.getSwapchainFormat(),
componentMapping,
subResourceRange
);
imageViews.push_back(context.getDevice().createImageView(imageViewCreateInfo));
}
return imageViews;
}
} }
...@@ -5,7 +5,8 @@ namespace vkcv ...@@ -5,7 +5,8 @@ namespace vkcv
PipelineManager::PipelineManager(vk::Device device) noexcept : PipelineManager::PipelineManager(vk::Device device) noexcept :
m_Device{device}, m_Device{device},
m_Pipelines{} m_Pipelines{},
m_Configs{}
{} {}
PipelineManager::~PipelineManager() noexcept PipelineManager::~PipelineManager() noexcept
...@@ -94,8 +95,8 @@ namespace vkcv ...@@ -94,8 +95,8 @@ namespace vkcv
//FIXME: hoping that order is the same and compatible: add explicit mapping and validation //FIXME: hoping that order is the same and compatible: add explicit mapping and validation
const VertexAttribute attribute = config.m_vertexAttributes[i]; const VertexAttribute attribute = config.m_vertexAttributes[i];
vertexAttributeDescriptions.push_back({location, binding, vertexFormatToVulkanFormat(attachment.format), 0}); vertexAttributeDescriptions.emplace_back(location, binding, vertexFormatToVulkanFormat(attachment.format), 0);
vertexBindingDescriptions.push_back(vk::VertexInputBindingDescription( vertexBindingDescriptions.emplace_back(vk::VertexInputBindingDescription(
binding, binding,
attribute.stride + getFormatSize(attachment.format), attribute.stride + getFormatSize(attachment.format),
vk::VertexInputRate::eVertex)); vk::VertexInputRate::eVertex));
...@@ -211,8 +212,19 @@ namespace vkcv ...@@ -211,8 +212,19 @@ namespace vkcv
break; break;
} }
} }
// graphics pipeline create std::vector<vk::DynamicState> dynamicStates = {};
if(config.m_Width == UINT32_MAX && config.m_Height == UINT32_MAX)
{
dynamicStates.push_back(vk::DynamicState::eViewport);
dynamicStates.push_back(vk::DynamicState::eScissor);
}
vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo({},
static_cast<uint32_t>(dynamicStates.size()),
dynamicStates.data());
// graphics pipeline create
std::vector<vk::PipelineShaderStageCreateInfo> shaderStages = { pipelineVertexShaderStageInfo, pipelineFragmentShaderStageInfo }; std::vector<vk::PipelineShaderStageCreateInfo> shaderStages = { pipelineVertexShaderStageInfo, pipelineFragmentShaderStageInfo };
const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(
{}, {},
...@@ -226,7 +238,7 @@ namespace vkcv ...@@ -226,7 +238,7 @@ namespace vkcv
&pipelineMultisampleStateCreateInfo, &pipelineMultisampleStateCreateInfo,
p_depthStencilCreateInfo, p_depthStencilCreateInfo,
&pipelineColorBlendStateCreateInfo, &pipelineColorBlendStateCreateInfo,
nullptr, &dynamicStateCreateInfo,
vkPipelineLayout, vkPipelineLayout,
pass, pass,
0, 0,
...@@ -247,6 +259,7 @@ namespace vkcv ...@@ -247,6 +259,7 @@ namespace vkcv
const uint64_t id = m_Pipelines.size(); const uint64_t id = m_Pipelines.size();
m_Pipelines.push_back({ vkPipeline, vkPipelineLayout }); m_Pipelines.push_back({ vkPipeline, vkPipelineLayout });
m_Configs.push_back(config);
return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); }); return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
} }
...@@ -293,5 +306,11 @@ namespace vkcv ...@@ -293,5 +306,11 @@ namespace vkcv
pipeline.m_layout = nullptr; pipeline.m_layout = nullptr;
} }
} }
const PipelineConfig &PipelineManager::getPipelineConfig(const PipelineHandle &handle) const
{
const uint64_t id = handle.getId();
return m_Configs.at(id);
}
} }
\ No newline at end of file
...@@ -18,6 +18,7 @@ namespace vkcv ...@@ -18,6 +18,7 @@ namespace vkcv
vk::Device m_Device; vk::Device m_Device;
std::vector<Pipeline> m_Pipelines; std::vector<Pipeline> m_Pipelines;
std::vector<PipelineConfig> m_Configs;
void destroyPipelineById(uint64_t id); void destroyPipelineById(uint64_t id);
...@@ -36,7 +37,11 @@ namespace vkcv ...@@ -36,7 +37,11 @@ namespace vkcv
[[nodiscard]] [[nodiscard]]
vk::Pipeline getVkPipeline(const PipelineHandle &handle) const; vk::Pipeline getVkPipeline(const PipelineHandle &handle) const;
[[nodiscard]] [[nodiscard]]
vk::PipelineLayout getVkPipelineLayout(const PipelineHandle &handle) const; vk::PipelineLayout getVkPipelineLayout(const PipelineHandle &handle) const;
[[nodiscard]]
const PipelineConfig &getPipelineConfig(const PipelineHandle &handle) const;
}; };
} }
#include "Surface.hpp"
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
namespace vkcv {
/**
* creates surface and checks availability
* @param window current window for the surface
* @param instance Vulkan-Instance
* @param physicalDevice Vulkan-PhysicalDevice
* @return created surface
*/
vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) {
//create surface
VkSurfaceKHR surface;
if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create a window surface!");
}
vk::Bool32 surfaceSupport = false;
if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) {
throw std::runtime_error("surface is not supported by the device!");
}
return vk::SurfaceKHR(surface);
}
}
#pragma once
#include <vulkan/vulkan.hpp>
struct GLFWwindow;
namespace vkcv {
vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice);
}
\ No newline at end of file
#include <vkcv/SwapChain.hpp> #include <vkcv/SwapChain.hpp>
#include <utility>
namespace vkcv { #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
SwapChain::SwapChain(vk::SurfaceKHR surface, vk::SwapchainKHR swapchain, vk::SurfaceFormatKHR format, uint32_t imageCount) namespace vkcv
: m_surface(surface), m_swapchain(swapchain), m_format( format), m_ImageCount(imageCount) {
/**
* creates surface and checks availability
* @param window current window for the surface
* @param instance Vulkan-Instance
* @param physicalDevice Vulkan-PhysicalDevice
* @return created surface
*/
vk::SurfaceKHR createSurface(GLFWwindow* window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice) {
//create surface
VkSurfaceKHR surface;
if (glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create a window surface!");
}
vk::Bool32 surfaceSupport = false;
if (physicalDevice.getSurfaceSupportKHR(0, vk::SurfaceKHR(surface), &surfaceSupport) != vk::Result::eSuccess && surfaceSupport != true) {
throw std::runtime_error("surface is not supported by the device!");
}
return vk::SurfaceKHR(surface);
}
SwapChain::SwapChain(const Surface &surface,
vk::SwapchainKHR swapchain,
vk::Format format,
vk::ColorSpaceKHR colorSpace,
vk::PresentModeKHR presentMode,
uint32_t imageCount,
vk::Extent2D extent) noexcept :
m_Surface(surface),
m_Swapchain(swapchain),
m_SwapchainFormat(format),
m_SwapchainColorSpace(colorSpace),
m_SwapchainPresentMode(presentMode),
m_SwapchainImageCount(imageCount),
m_Extent(extent),
m_RecreationRequired(false)
{} {}
SwapChain::SwapChain(const SwapChain &other) :
m_Surface(other.m_Surface),
m_Swapchain(other.m_Swapchain),
m_SwapchainFormat(other.m_SwapchainFormat),
m_SwapchainColorSpace(other.m_SwapchainColorSpace),
m_SwapchainPresentMode(other.m_SwapchainPresentMode),
m_SwapchainImageCount(other.m_SwapchainImageCount),
m_Extent(other.m_Extent),
m_RecreationRequired(other.m_RecreationRequired.load())
{}
const vk::SwapchainKHR& SwapChain::getSwapchain() const { const vk::SwapchainKHR& SwapChain::getSwapchain() const {
return m_swapchain; return m_Swapchain;
} }
/** vk::SurfaceKHR SwapChain::getSurface() const {
* gets surface of the swapchain return m_Surface.handle;
* @return current surface
*/
vk::SurfaceKHR SwapChain::getSurface() {
return m_surface;
} }
/** vk::Format SwapChain::getSwapchainFormat() const{
* gets the surface of the swapchain return m_SwapchainFormat;
* @return chosen format
*/
vk::SurfaceFormatKHR SwapChain::getSurfaceFormat(){
return m_format;
} }
/** /**
...@@ -33,7 +74,7 @@ namespace vkcv { ...@@ -33,7 +74,7 @@ namespace vkcv {
* @param window of the current application * @param window of the current application
* @return chosen Extent for the surface * @return chosen Extent for the surface
*/ */
vk::Extent2D chooseSwapExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){ vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){
vk::SurfaceCapabilitiesKHR surfaceCapabilities; vk::SurfaceCapabilitiesKHR surfaceCapabilities;
if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){ if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){
throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface."); throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface.");
...@@ -43,15 +84,10 @@ namespace vkcv { ...@@ -43,15 +84,10 @@ namespace vkcv {
static_cast<uint32_t>(window.getWidth()), static_cast<uint32_t>(window.getWidth()),
static_cast<uint32_t>(window.getHeight()) static_cast<uint32_t>(window.getHeight())
}; };
extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width));
extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height));
if (extent2D.width > surfaceCapabilities.maxImageExtent.width ||
extent2D.width < surfaceCapabilities.minImageExtent.width ||
extent2D.height > surfaceCapabilities.maxImageExtent.height ||
extent2D.height < surfaceCapabilities.minImageExtent.height) {
std::printf("Surface size not matching. Resizing to allowed value.");
}
return extent2D; return extent2D;
} }
...@@ -61,7 +97,7 @@ namespace vkcv { ...@@ -61,7 +97,7 @@ namespace vkcv {
* @param surface of the swapchain * @param surface of the swapchain
* @return available Format * @return available Format
*/ */
vk::SurfaceFormatKHR chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { vk::SurfaceFormatKHR chooseSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) {
uint32_t formatCount; uint32_t formatCount;
physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr); physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr);
std::vector<vk::SurfaceFormatKHR> availableFormats(formatCount); std::vector<vk::SurfaceFormatKHR> availableFormats(formatCount);
...@@ -126,23 +162,29 @@ namespace vkcv { ...@@ -126,23 +162,29 @@ namespace vkcv {
* @param context that keeps instance, physicalDevice and a device. * @param context that keeps instance, physicalDevice and a device.
* @return swapchain * @return swapchain
*/ */
SwapChain SwapChain::create(const Window &window, const Context &context, const vk::SurfaceKHR surface) { SwapChain SwapChain::create(const Window &window, const Context &context) {
const vk::Instance& instance = context.getInstance(); const vk::Instance& instance = context.getInstance();
const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice(); const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
const vk::Device& device = context.getDevice(); const vk::Device& device = context.getDevice();
vk::Extent2D extent2D = chooseSwapExtent(physicalDevice, surface, window); Surface surface;
vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(physicalDevice, surface); surface.handle = createSurface(window.getWindow(), instance, physicalDevice);
vk::PresentModeKHR presentMode = choosePresentMode(physicalDevice, surface); surface.formats = physicalDevice.getSurfaceFormatsKHR(surface.handle);
uint32_t imageCount = chooseImageCount(physicalDevice, surface); surface.capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.handle);
surface.presentModes = physicalDevice.getSurfacePresentModesKHR(surface.handle);
vk::Extent2D chosenExtent = chooseExtent(physicalDevice, surface.handle, window);
vk::SurfaceFormatKHR chosenSurfaceFormat = chooseSurfaceFormat(physicalDevice, surface.handle);
vk::PresentModeKHR chosenPresentMode = choosePresentMode(physicalDevice, surface.handle);
uint32_t chosenImageCount = chooseImageCount(physicalDevice, surface.handle);
vk::SwapchainCreateInfoKHR swapchainCreateInfo( vk::SwapchainCreateInfoKHR swapchainCreateInfo(
vk::SwapchainCreateFlagsKHR(), //flags vk::SwapchainCreateFlagsKHR(), //flags
surface, // surface surface.handle, // surface
imageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -> 3 for Triple Buffering, else 2 for Double Buffering (should be the standard) chosenImageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -> 3 for Triple Buffering, else 2 for Double Buffering (should be the standard)
surfaceFormat.format, // imageFormat chosenSurfaceFormat.format, // imageFormat
surfaceFormat.colorSpace, // imageColorSpace chosenSurfaceFormat.colorSpace, // imageColorSpace
extent2D, // imageExtent chosenExtent, // imageExtent
1, // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers" 1, // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers"
vk::ImageUsageFlagBits::eColorAttachment, // imageUsage TODO: what attachments? only color? depth? vk::ImageUsageFlagBits::eColorAttachment, // imageUsage TODO: what attachments? only color? depth?
vk::SharingMode::eExclusive, // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues" vk::SharingMode::eExclusive, // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues"
...@@ -150,22 +192,71 @@ namespace vkcv { ...@@ -150,22 +192,71 @@ namespace vkcv {
nullptr, // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT nullptr, // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT
vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display
vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque
presentMode, // presentMode chosenPresentMode, // presentMode
true, // clipped true, // clipped
nullptr // oldSwapchain nullptr // oldSwapchain
); );
vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo); vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchainCreateInfo);
return SwapChain(surface, swapchain, surfaceFormat, imageCount); return SwapChain(surface,
swapchain,
chosenSurfaceFormat.format,
chosenSurfaceFormat.colorSpace,
chosenPresentMode,
chosenImageCount,
chosenExtent);
}
bool SwapChain::shouldUpdateSwapchain() const {
return m_RecreationRequired;
}
void SwapChain::updateSwapchain(const Context &context, const Window &window) {
if (!m_RecreationRequired.exchange(false))
return;
vk::SwapchainKHR oldSwapchain = m_Swapchain;
vk::Extent2D extent2D = chooseExtent(context.getPhysicalDevice(), m_Surface.handle, window);
vk::SwapchainCreateInfoKHR swapchainCreateInfo(
vk::SwapchainCreateFlagsKHR(),
m_Surface.handle,
m_SwapchainImageCount,
m_SwapchainFormat,
m_SwapchainColorSpace,
extent2D,
1,
vk::ImageUsageFlagBits::eColorAttachment,
vk::SharingMode::eExclusive,
0,
nullptr,
vk::SurfaceTransformFlagBitsKHR::eIdentity,
vk::CompositeAlphaFlagBitsKHR::eOpaque,
m_SwapchainPresentMode,
true,
oldSwapchain
);
m_Swapchain = context.getDevice().createSwapchainKHR(swapchainCreateInfo);
context.getDevice().destroySwapchainKHR(oldSwapchain);
m_Extent = extent2D;
} }
void SwapChain::recreateSwapchain() {
m_RecreationRequired = true;
}
const vk::Extent2D& SwapChain::getExtent() const {
return m_Extent;
}
SwapChain::~SwapChain() { SwapChain::~SwapChain() {
// needs to be destroyed by creator // needs to be destroyed by creator
} }
uint32_t SwapChain::getImageCount() { uint32_t SwapChain::getImageCount() {
return m_ImageCount; return m_SwapchainImageCount;
} }
} }