Skip to content

Commit

Permalink
WIP added swap chain rebuild
Browse files Browse the repository at this point in the history
  • Loading branch information
lromor committed Sep 2, 2020
1 parent 1c8f87d commit b3a9ce6
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 64 deletions.
44 changes: 31 additions & 13 deletions scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// This file contains the basic ingredients to render a basic wireframed scene.
// This simple scene allows you to add meshes and a freely "movable" camera.

#include <bits/stdint-uintn.h>
#include <unistd.h>
#include <iostream>
#include <optional>
Expand Down Expand Up @@ -67,10 +68,10 @@ void Scene::Init() {
pipeline_cache_ =
device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo());

CreateSwapChain();
CreateSwapChainContext();
}

void Scene::CreateSwapChain() {
void Scene::CreateSwapChainContext() {
vk::PhysicalDevice &physical_device = vk_ctx_->physical_device;
space::core::SurfaceData &surface_data = vk_ctx_->surface_data;
vk::UniqueDevice &device = vk_ctx_->device;
Expand All @@ -86,8 +87,8 @@ void Scene::CreateSwapChain() {
space::core::SwapChainData swap_chain_data(
physical_device, device, *surface_data.surface, surface_data.extent,
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(), graphics_queue_family_index,
present_queue_family_index);
swap_chain_context_ ? std::move(swap_chain_context_->swap_chain_data.swap_chain) : vk::UniqueSwapchainKHR(),
graphics_queue_family_index, present_queue_family_index);

space::core::DepthBufferData depth_buffer_data(
physical_device, device, vk::Format::eD16Unorm, surface_data.extent);
Expand Down Expand Up @@ -127,6 +128,11 @@ void Scene::CreateSwapChain() {
std::move(descriptor_pool), std::move(descriptor_set)};

swap_chain_context_.reset(swap_chain_context);

for (const auto entity : entities_) {
entity->Register(vk_ctx_, &pipeline_layout_, &swap_chain_context_->render_pass,
&pipeline_cache_);
}
}

void Scene::AddEntity(space::Entity *entity) {
Expand Down Expand Up @@ -158,13 +164,19 @@ void Scene::SubmitRendering() {

// Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo());
vk::ResultValue<uint32_t> res =
device->acquireNextImageKHR(
swap_chain_data.swap_chain.get(), FENCE_TIMEOUT,
imageAcquiredSemaphore.get(), nullptr);
assert(res.result == vk::Result::eSuccess);
assert(res.value < swap_chain_context_->framebuffers.size());
current_buffer_ = res.value;

try {
vk::ResultValue<uint32_t> res =
device->acquireNextImageKHR(
swap_chain_data.swap_chain.get(), FENCE_TIMEOUT,
imageAcquiredSemaphore.get(), nullptr);
assert(res.result == vk::Result::eSuccess);
assert(res.value < swap_chain_context_->framebuffers.size());
current_buffer_ = res.value;
} catch (vk::OutOfDateKHRError e) {
CreateSwapChainContext();
}

command_buffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags()));

vk::ClearValue clear_values[2];
Expand Down Expand Up @@ -210,8 +222,14 @@ void Scene::Present() {

while (vk::Result::eTimeout
== device->waitForFences(draw_fence_.get(), VK_TRUE, FENCE_TIMEOUT)) { usleep(1000); }
present_queue.presentKHR(
vk::PresentInfoKHR(0, nullptr, 1, &swap_chain_data.swap_chain.get(), &current_buffer_));

try {
present_queue.presentKHR(
vk::PresentInfoKHR(0, nullptr, 1, &swap_chain_data.swap_chain.get(), &current_buffer_));
} catch (vk::OutOfDateKHRError e) {
CreateSwapChainContext();
}

}


Expand Down
4 changes: 3 additions & 1 deletion scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Scene {
void Input(CameraControls &input);
void SubmitRendering();
void Present();
void WindowResizeEvent(int width, int height);


private:
space::core::VkAppContext *const vk_ctx_;
Expand Down Expand Up @@ -87,7 +89,7 @@ class Scene {
std::unique_ptr<SwapChainContext> swap_chain_context_;

// Creates a new swapchain and returns the old one.
void CreateSwapChain();
void CreateSwapChainContext();

uint32_t current_buffer_;

Expand Down
11 changes: 10 additions & 1 deletion space.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>

#include <X11/X.h>
#include <iostream>
#include <optional>
#include <memory>
Expand Down Expand Up @@ -148,6 +149,7 @@ int main(int argc, char *argv[]) {
XSelectInput(display, window,
ExposureMask
| KeyPressMask
| StructureNotifyMask
| PointerMotionMask);
XMapWindow(display, window);
XFlush(display);
Expand Down Expand Up @@ -189,8 +191,15 @@ int main(int argc, char *argv[]) {
if (FD_ISSET(x11_fd, &read_fds)) {
while(XPending(display)) {
XNextEvent(display, &e);
if (e.type == KeyPress) {

switch (e.type) {
case KeyPress:
exit = true;
break;
case ConfigureNotify:
scene.WindowResizeEvent(
e.xconfigure.width, e.xconfigure.height);
break;
}
}
}
Expand Down
24 changes: 4 additions & 20 deletions vulkan-core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,6 @@ std::optional<std::pair<uint32_t, uint32_t>> FindGraphicsAndPresentQueueFamilyIn
return {};
}

std::optional<vk::Extent2D> get_xlib_window_extent(Display *display, Window window) {
XWindowAttributes attrs;
if (XGetWindowAttributes(display, window, &attrs)) {
return vk::Extent2D(attrs.width, attrs.height);
}
return {};
}

vk::UniqueDevice CreateDevice(
vk::PhysicalDevice physical_device, uint32_t queue_family_index,
std::vector<std::string> const& extensions = {},
Expand Down Expand Up @@ -321,23 +313,15 @@ namespace space {
// possibly configurable policy.
vk::PhysicalDevice physical_device = instance->enumeratePhysicalDevices().front();

vk::Extent2D extent;
if (auto res = get_xlib_window_extent(display, window)) {
extent = res.value();
} else {
fprintf(stderr, "Coudldn't guess the xlib window extent.");
return {};
}
// Init the surface
struct SurfaceData surface_data = {
vk::UniqueSurfaceKHR surface =
instance->createXlibSurfaceKHRUnique(
vk::XlibSurfaceCreateInfoKHR(vk::XlibSurfaceCreateFlagsKHR(), display, window)),
extent};
vk::XlibSurfaceCreateInfoKHR(vk::XlibSurfaceCreateFlagsKHR(), display, window));

// Find devices for present and graphics.
std::pair<uint32_t, uint32_t> graphics_and_present_queue_family_index;
if (const auto o = FindGraphicsAndPresentQueueFamilyIndex(
physical_device, *surface_data.surface)) {
physical_device, *surface)) {
graphics_and_present_queue_family_index = o.value();
} else {
fprintf(stderr, "Couldn't find suitable Present or Graphics queues.");
Expand All @@ -358,7 +342,7 @@ namespace space {
return VkAppContext{
std::move(dl), std::move(instance), std::move(device),
std::move(debug_utils_messenger),
physical_device, std::move(surface_data),
physical_device, std::move(surface),
graphics_and_present_queue_family_index.first,
graphics_and_present_queue_family_index.second};
}
Expand Down
24 changes: 11 additions & 13 deletions vulkan-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,28 @@ VULKAN_HPP_INLINE TargetType checked_cast(SourceType value) {

namespace space {
namespace core {
// Vulkan initialization routines
struct SurfaceData {
vk::UniqueSurfaceKHR surface;
vk::Extent2D extent;
};

// Hold the Vulkan configuration data
// such as application name, engine,
// and requested instance layers and extensions.
struct VkAppConfig {
const char *app_name;
const char *engine_name;
std::vector<std::string> instance_layers;
std::vector<std::string> instance_extensions;
};

// Holds the vulkan datacstructures
// used to represent the vulkan implementation,
// instantiation and configuration. It does not
// include any rendering related vullkan calls or
// data structures.
struct VkAppContext {
vk::DynamicLoader dynamic_loader;
vk::UniqueInstance instance;
vk::UniqueSurfaceKHR surface;
vk::UniqueDevice device;
vk::UniqueDebugUtilsMessengerEXT debug_utils_messenger;
vk::PhysicalDevice physical_device;
SurfaceData surface_data;
uint32_t graphics_queue_family_index;
uint32_t present_queue_family_index;
};
Expand All @@ -78,13 +80,9 @@ namespace space {
// Vulkan rendering helper routines
struct SwapChainData {
SwapChainData(
vk::PhysicalDevice const& physical_device,
vk::UniqueDevice const& device,
vk::SurfaceKHR const& surface, vk::Extent2D const& extent,
VkAppContext const& vk_ctx, vk::Extent2D const& extent,
vk::ImageUsageFlags usage,
vk::UniqueSwapchainKHR const& old_swap_chain,
uint32_t graphics_family_index,
uint32_t present_family_index);
vk::UniqueSwapchainKHR const& old_swap_chain);
vk::Format color_format;
vk::UniqueSwapchainKHR swap_chain;
std::vector<vk::Image> images;
Expand Down
30 changes: 14 additions & 16 deletions vulkan-rendering.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// found here.

#include <numeric>
#include <vulkan/vulkan.hpp>

#include "vulkan-core.h"

Expand All @@ -38,7 +39,7 @@ static std::optional<vk::PresentModeKHR> PickPresentMode(
return picked_mode;
}

static std::optional<vk::SurfaceFormatKHR> PickSurfaceFormat(
std::optional<vk::SurfaceFormatKHR> PickSurfaceFormat(
std::vector<vk::SurfaceFormatKHR> const& formats) {
assert(!formats.empty());
vk::SurfaceFormatKHR picked_format = formats[0];
Expand Down Expand Up @@ -78,17 +79,14 @@ static std::optional<vk::SurfaceFormatKHR> PickSurfaceFormat(
namespace space {
namespace core {
SwapChainData::SwapChainData(
vk::PhysicalDevice const& physical_device, vk::UniqueDevice const& device,
vk::SurfaceKHR const& surface, vk::Extent2D const& extent, vk::ImageUsageFlags usage,
vk::UniqueSwapchainKHR const& old_swap_chain, uint32_t graphics_queue_family_index,
uint32_t present_queue_family_index) {

vk::SurfaceFormatKHR surface_format =PickSurfaceFormat(
physical_device.getSurfaceFormatsKHR(surface)).value();
VkAppContext const& vk_ctx, vk::Extent2D const& extent, vk::ImageUsageFlags usage,
vk::UniqueSwapchainKHR const& old_swap_chain) {
vk::SurfaceFormatKHR surface_format = PickSurfaceFormat(
vk_ctx.physical_device.getSurfaceFormatsKHR(*vk_ctx.surface)).value();
color_format = surface_format.format;

vk::SurfaceCapabilitiesKHR surface_capabilities =
physical_device.getSurfaceCapabilitiesKHR(surface);
vk_ctx.physical_device.getSurfaceCapabilitiesKHR(*vk_ctx.surface);
VkExtent2D swap_chain_extent;
if (surface_capabilities.currentExtent.width
== std::numeric_limits<uint32_t>::max()) {
Expand Down Expand Up @@ -120,25 +118,25 @@ namespace space {
? vk::CompositeAlphaFlagBitsKHR::eInherit
: vk::CompositeAlphaFlagBitsKHR::eOpaque;
vk::PresentModeKHR present_mode = PickPresentMode(
physical_device.getSurfacePresentModesKHR(surface)).value();
vk_ctx.physical_device.getSurfacePresentModesKHR(*vk_ctx.surface)).value();
vk::SwapchainCreateInfoKHR swapChainCreateInfo(
{}, surface, surface_capabilities.minImageCount,
{}, *vk_ctx.surface, surface_capabilities.minImageCount,
color_format, surface_format.colorSpace, swap_chain_extent,
1, usage, vk::SharingMode::eExclusive, 0, nullptr,
pre_transform, composite_alpha, present_mode, true, *old_swap_chain);
if (graphics_queue_family_index != present_queue_family_index) {
if (vk_ctx.graphics_queue_family_index != vk_ctx.present_queue_family_index) {
uint32_t queueFamilyIndices[2] =
{ graphics_queue_family_index, present_queue_family_index };
{ vk_ctx.graphics_queue_family_index, vk_ctx.present_queue_family_index };
// If the graphics and present queues are from different queue families, we either have to
// explicitly transfer ownership of images between the queues, or we have to create the
// swapchain with imageSharingMode as vk::SharingMode::eConcurrent
swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
swapChainCreateInfo.queueFamilyIndexCount = 2;
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
}
swap_chain = device->createSwapchainKHRUnique(swapChainCreateInfo);
swap_chain = vk_ctx.device->createSwapchainKHRUnique(swapChainCreateInfo);

images = device->getSwapchainImagesKHR(swap_chain.get());
images = vk_ctx.device->getSwapchainImagesKHR(swap_chain.get());

image_views.reserve(images.size());
vk::ComponentMapping component_mapping(
Expand All @@ -150,7 +148,7 @@ namespace space {
vk::ImageViewCreateInfo image_view_create_info(
vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, color_format,
component_mapping, sub_resource_range);
image_views.push_back(device->createImageViewUnique(image_view_create_info));
image_views.push_back(vk_ctx.device->createImageViewUnique(image_view_create_info));
}
}

Expand Down

0 comments on commit b3a9ce6

Please sign in to comment.