summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChuyan Zhang <me@zcy.moe>2024-09-07 00:40:38 -0700
committerChuyan Zhang <me@zcy.moe>2024-09-07 00:40:38 -0700
commit2ead02037dc89e987fbc0a021fe470e29d226cfd (patch)
tree473011eda50080299be844e69f82cec75aa4fb95
parente12ca33626bdadedc3158cb69f2a4d2f9bbeeeb0 (diff)
downloadiris-2ead02037dc89e987fbc0a021fe470e29d226cfd.tar.gz
iris-2ead02037dc89e987fbc0a021fe470e29d226cfd.zip
Add more encapsulation, use VMA for allocation
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt14
m---------ext/VulkanMemoryAllocator0
-rw-r--r--src/app.cpp32
-rw-r--r--src/vulkan_helper.cpp91
-rw-r--r--src/vulkan_helper.h45
-rw-r--r--src/vulkan_swapchain.cpp208
-rw-r--r--src/vulkan_swapchain.h7
8 files changed, 280 insertions, 120 deletions
diff --git a/.gitmodules b/.gitmodules
index 3c3f029..6ea0b14 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,3 +10,6 @@
[submodule "ext/tinygltf.git"]
path = ext/tinygltf.git
url = https://github.com/syoyo/tinygltf.git
+[submodule "ext/VulkanMemoryAllocator"]
+ path = ext/VulkanMemoryAllocator
+ url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0cedde2..41401be 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,22 +21,24 @@ target_include_directories(tinygltf INTERFACE ${EXT_DIR}/tinygltf)
add_library(tinyobjloader INTERFACE)
target_include_directories(tinyobjloader INTERFACE ${EXT_DIR}/tinyobjloader)
-# Add your project's source files
file(GLOB_RECURSE SOURCES "${SRC_DIR}/*.cpp")
# Add executable from your source files
add_executable(IrisRenderer ${SOURCES})
-# find_package(glfw3 REQUIRED)
-# target_link_libraries(IrisRenderer PRIVATE glfw)
+find_package(glfw3 REQUIRED)
+target_link_libraries(IrisRenderer PRIVATE glfw)
-# find_package(Vulkan REQUIRED)
-# target_link_libraries(IrisRenderer PRIVATE Vulkan::Vulkan)
+find_package(Vulkan REQUIRED)
+target_link_libraries(IrisRenderer PRIVATE Vulkan::Vulkan)
+
+find_package(VulkanMemoryAllocator REQUIRED)
+target_link_libraries(IrisRenderer PRIVATE GPUOpen::VulkanMemoryAllocator)
# Link external libraries to your project
target_link_libraries(IrisRenderer PRIVATE
argparse imgui tinygltf tinyobjloader
- glfw vulkan dl pthread X11 Xxf86vm Xrandr Xi)
+ dl pthread X11 Xxf86vm Xrandr Xi)
# Optional: Include additional compiler options or flags
target_compile_options(IrisRenderer PRIVATE -Wall -Wextra -Wno-missing-field-initializers)
diff --git a/ext/VulkanMemoryAllocator b/ext/VulkanMemoryAllocator
new file mode 160000
+Subproject 1c35ba99ce775f8342d87a83a3f0f696f99c2a3
diff --git a/src/app.cpp b/src/app.cpp
index b3df2a5..a5b3247 100644
--- a/src/app.cpp
+++ b/src/app.cpp
@@ -1,9 +1,9 @@
#include "vulkan_swapchain.h"
-#include "imgui.h"
-#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include "argparse/argparse.hpp"
+#include <cstdint>
+#include <sys/types.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
@@ -15,12 +15,6 @@
std::unique_ptr<iris::Swapchain> start_up(int width, int height) {
auto glfw_extensions = get_glfw_instance_extensions();
- // std::vector<const char*> glfw_extensions = {
- // "VK_KHR_surface",
- // };
- // for (const auto& extension : glfw_extensions) {
- // std::cerr << "GLFW extension: " << extension << std::endl;
- // }
iris::Device device({}, glfw_extensions);
auto window = glfwCreateWindow(width, height, "IrisRenderer", nullptr, nullptr);
@@ -31,10 +25,6 @@ std::unique_ptr<iris::Swapchain> start_up(int width, int height) {
return std::make_unique<iris::Swapchain>(window, device);
}
-void main_loop(GLFWwindow *window) {
- (void) window;
-}
-
void shut_down(std::unique_ptr<iris::Swapchain>& swapchain) {
ImGui_ImplVulkan_Shutdown();
@@ -77,7 +67,23 @@ int main(int argc, char** argv) {
auto swapchain = start_up(window_width, window_height);
while (!glfwWindowShouldClose(swapchain->window)) {
- main_loop(swapchain->window);
+ glfwPollEvents();
+
+ int display_w, display_h;
+ glfwGetFramebufferSize(swapchain->window, &display_w, &display_h);
+ if (display_w == 0 || display_h == 0) {
+ break;
+ }
+
+ swapchain->needs_recreate |=
+ (uint32_t) display_w != swapchain->width ||
+ (uint32_t) display_h != swapchain->height;
+ if (swapchain->needs_recreate) {
+ swapchain->resize(display_w, display_h);
+ swapchain->needs_recreate = false;
+ }
+
+ ImGui_ImplVulkan_NewFrame();
}
shut_down(swapchain);
diff --git a/src/vulkan_helper.cpp b/src/vulkan_helper.cpp
index 84a2b6d..e533d2d 100644
--- a/src/vulkan_helper.cpp
+++ b/src/vulkan_helper.cpp
@@ -3,17 +3,19 @@
#include <cstdint>
#include <cstdlib>
#include <iostream>
+#include <memory>
+#include <vk_mem_alloc.h>
namespace iris {
-Device::Device(std::vector<std::string> layers, std::vector<std::string> instance_extensions) {
+Device::Device(std::vector<std::string> layers, std::vector<std::string> instance_extensions) {
VkApplicationInfo app_info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pApplicationName = "IrisRenderer",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "No Engine",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
- .apiVersion = VK_API_VERSION_1_0,
+ .apiVersion = VK_API_VERSION_1_3,
};
// Create the Vulkan instance
@@ -140,6 +142,91 @@ Device::Device(std::vector<std::string> layers, std::vector<std::string> instan
main_queue_family_index,
0,
&graphics_queue);
+
+ // Create the memory allocator
+ VmaAllocatorCreateInfo allocator_info = {
+ .physicalDevice = physical_device,
+ .device = device,
+ .instance = instance,
+ };
+ CHECK_VULKAN(vmaCreateAllocator(
+ &allocator_info,
+ &allocator));
+}
+
+Device::~Device() {
+ vmaDestroyAllocator(allocator);
+ vkDestroyDevice(device, VK_NULL_HANDLE);
+ vkDestroyInstance(instance, VK_NULL_HANDLE);
+}
+
+
+Buffer_t::~Buffer_t() {
+ vmaDestroyBuffer(allocator, buffer, allocation);
+}
+
+Buffer Device::create_buffer(VkDeviceSize size,
+ VkBufferUsageFlags usage,
+ VmaMemoryUsage memory_usage) {
+ VkBufferCreateInfo buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .size = size,
+ .usage = usage,
+ };
+ VmaAllocationCreateInfo allocation_info = {
+ .usage = memory_usage,
+ };
+ Buffer_t buffer = {
+ .allocator = this->allocator,
+ .flags = usage,
+ .size = size,
+ };
+ CHECK_VULKAN(vmaCreateBuffer(
+ allocator,
+ &buffer_info,
+ &allocation_info,
+ &buffer.buffer,
+ &buffer.allocation,
+ VK_NULL_HANDLE));
+ return std::make_shared<Buffer_t>(buffer);
+}
+
+Texture2D_t::~Texture2D_t() {
+ vmaDestroyImage(allocator, image, allocation);
+ // TODO: optionally destroy image view, if created
+}
+
+Texture2D Device::create_texture(VkExtent2D extent,
+ VkFormat format,
+ VkImageUsageFlags usage,
+ VmaMemoryUsage memory_usage) {
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = format,
+ .extent = {extent.width, extent.height, 1},
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = usage,
+ };
+ VmaAllocationCreateInfo allocation_info = {
+ .usage = memory_usage,
+ };
+ Texture2D_t texture = {
+ .allocator = this->allocator,
+ .flags = usage,
+ .extent = extent,
+ };
+ CHECK_VULKAN(vmaCreateImage(
+ allocator,
+ &image_info,
+ &allocation_info,
+ &texture.image,
+ &texture.allocation,
+ VK_NULL_HANDLE));
+ return std::make_shared<Texture2D_t>(texture);
}
} // namespace iris \ No newline at end of file
diff --git a/src/vulkan_helper.h b/src/vulkan_helper.h
index 089a09f..b6f270a 100644
--- a/src/vulkan_helper.h
+++ b/src/vulkan_helper.h
@@ -1,5 +1,8 @@
-#include <cstdint>
+#include <memory>
#include <vulkan/vulkan_core.h>
+#include <vk_mem_alloc.h>
+
+#include <cstdint>
#include <vector>
#include <string>
@@ -15,16 +18,56 @@
namespace iris {
+struct Buffer_t {
+ VkBuffer buffer;
+ VmaAllocator allocator;
+ VmaAllocation allocation;
+
+ VkBufferUsageFlags flags;
+ VkDeviceSize size;
+
+ ~Buffer_t();
+};
+
+typedef std::shared_ptr<Buffer_t> Buffer;
+
+struct Texture2D_t {
+ VkImage image;
+ VmaAllocator allocator;
+ VmaAllocation allocation;
+ VkImageView image_view;
+
+ VkImageUsageFlags flags;
+ VkExtent2D extent;
+
+ ~Texture2D_t();
+};
+
+typedef std::shared_ptr<Texture2D_t> Texture2D;
+
struct Device {
VkInstance instance;
VkPhysicalDevice physical_device;
VkDevice device;
uint32_t main_queue_family_index;
VkQueue graphics_queue;
+ VmaAllocator allocator;
Device(
std::vector<std::string> layers,
std::vector<std::string> instance_extensions);
+ ~Device();
+
+ Buffer create_buffer(
+ VkDeviceSize size,
+ VkBufferUsageFlags usage,
+ VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_AUTO);
+
+ Texture2D create_texture(
+ VkExtent2D extent,
+ VkFormat format,
+ VkImageUsageFlags usage,
+ VmaMemoryUsage memory_usage = VMA_MEMORY_USAGE_AUTO);
};
} // namespace iris \ No newline at end of file
diff --git a/src/vulkan_swapchain.cpp b/src/vulkan_swapchain.cpp
index 651b558..fde4388 100644
--- a/src/vulkan_swapchain.cpp
+++ b/src/vulkan_swapchain.cpp
@@ -10,6 +10,7 @@
#include <vector>
#include <iostream>
#include <string>
+#include <vk_mem_alloc.h>
std::vector<std::string> get_glfw_instance_extensions() {
uint32_t extension_count = 0;
@@ -25,6 +26,116 @@ std::vector<std::string> get_glfw_instance_extensions() {
namespace iris {
+void Swapchain::resize(uint32_t new_width, uint32_t new_height) {
+ width = new_width;
+ height = new_height;
+
+ // wait for the device to finish
+ CHECK_VULKAN(vkDeviceWaitIdle(device.device));
+
+ // destroy old resources
+ if (swapchain != VK_NULL_HANDLE) {
+ for (uint32_t i = 0; i < SWAPCHAIN_IMAGE_COUNT; i++) {
+ vkDestroyFramebuffer(device.device, framebuffers[i], nullptr);
+ vkDestroyImageView(device.device, swapchain_image_views[i], nullptr);
+ }
+ vkDestroySwapchainKHR(device.device, swapchain, nullptr);
+ }
+
+ VkSwapchainCreateInfoKHR swapchain_create_info = {
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ .surface = surface,
+ .minImageCount = SWAPCHAIN_IMAGE_COUNT,
+ .imageFormat = VK_FORMAT_B8G8R8A8_UNORM,
+ .imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ .imageExtent = {width, height},
+ .imageArrayLayers = 1,
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
+ .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR,
+ .clipped = VK_TRUE,
+ .oldSwapchain = VK_NULL_HANDLE,
+ };
+ CHECK_VULKAN(vkCreateSwapchainKHR(
+ device.device,
+ &swapchain_create_info,
+ nullptr,
+ &swapchain));
+
+ // images
+ uint32_t image_count = 0;
+ CHECK_VULKAN(vkGetSwapchainImagesKHR(
+ device.device,
+ swapchain,
+ &image_count,
+ nullptr));
+ if (image_count > SWAPCHAIN_IMAGE_COUNT) {
+ // TODO throw an exception
+ std::cerr << "Swapchain image count is greater than expected" << std::endl;
+ abort();
+ }
+ CHECK_VULKAN(vkGetSwapchainImagesKHR(
+ device.device,
+ swapchain,
+ &image_count,
+ swapchain_images));
+
+ // image views
+ for (uint32_t i = 0; i < image_count; i++) {
+ VkImageViewCreateInfo image_view_create_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = swapchain_images[i],
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
+ .format = VK_FORMAT_B8G8R8A8_UNORM,
+ .components = {
+ .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+ },
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ };
+
+ CHECK_VULKAN(vkCreateImageView(
+ device.device,
+ &image_view_create_info,
+ nullptr,
+ &swapchain_image_views[i]));
+ }
+
+ // framebuffers
+ for (uint32_t i = 0; i < image_count; i++) {
+ VkFramebufferCreateInfo frame_buffer_create_info = {
+ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ .renderPass = render_pass,
+ .attachmentCount = 1,
+ .pAttachments = &swapchain_image_views[i],
+ .width = width,
+ .height = height,
+ .layers = 1,
+ };
+ CHECK_VULKAN(vkCreateFramebuffer(
+ device.device,
+ &frame_buffer_create_info,
+ nullptr,
+ &framebuffers[i]));
+ }
+
+ upload_texture = device.create_texture(
+ {width, height},
+ VK_FORMAT_B8G8R8A8_UNORM,
+ VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+ VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE);
+}
+
Swapchain::Swapchain(
GLFWwindow *window,
iris::Device device) : device(device), window(window)
@@ -129,102 +240,7 @@ Swapchain::Swapchain(
&render_pass));
// Create swapchain and image/imageview/framebuffers
- // TODO: move this into `resize` to support resizing
- {
- // swapchain
- int i_width, i_height;
- glfwGetFramebufferSize(window, &i_width, &i_height);
- width = (uint32_t) i_width;
- height = (uint32_t) i_height;
-
- VkSwapchainCreateInfoKHR swapchain_create_info = {
- .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
- .surface = surface,
- .minImageCount = SWAPCHAIN_IMAGE_COUNT,
- .imageFormat = VK_FORMAT_B8G8R8A8_UNORM,
- .imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
- .imageExtent = {width, height},
- .imageArrayLayers = 1,
- .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
- .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
- .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
- .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
- .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR,
- .clipped = VK_TRUE,
- .oldSwapchain = VK_NULL_HANDLE,
- };
- CHECK_VULKAN(vkCreateSwapchainKHR(
- device.device,
- &swapchain_create_info,
- nullptr,
- &swapchain));
-
- // images
- uint32_t image_count = 0;
- CHECK_VULKAN(vkGetSwapchainImagesKHR(
- device.device,
- swapchain,
- &image_count,
- nullptr));
- if (image_count > SWAPCHAIN_IMAGE_COUNT) {
- // TODO throw an exception
- std::cerr << "Swapchain image count is greater than expected" << std::endl;
- abort();
- }
- CHECK_VULKAN(vkGetSwapchainImagesKHR(
- device.device,
- swapchain,
- &image_count,
- swapchain_images));
-
- // image views
- for (uint32_t i = 0; i < image_count; i++) {
- VkImageViewCreateInfo image_view_create_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = swapchain_images[i],
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = VK_FORMAT_B8G8R8A8_UNORM,
- .components = {
- .r = VK_COMPONENT_SWIZZLE_IDENTITY,
- .g = VK_COMPONENT_SWIZZLE_IDENTITY,
- .b = VK_COMPONENT_SWIZZLE_IDENTITY,
- .a = VK_COMPONENT_SWIZZLE_IDENTITY,
- },
- .subresourceRange = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- };
-
- CHECK_VULKAN(vkCreateImageView(
- device.device,
- &image_view_create_info,
- nullptr,
- &swapchain_image_views[i]));
- }
-
- // framebuffers
- for (uint32_t i = 0; i < image_count; i++) {
- VkFramebufferCreateInfo frame_buffer_create_info = {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .renderPass = render_pass,
- .attachmentCount = 1,
- .pAttachments = &swapchain_image_views[i],
- .width = width,
- .height = height,
- .layers = 1,
- };
- CHECK_VULKAN(vkCreateFramebuffer(
- device.device,
- &frame_buffer_create_info,
- nullptr,
- &framebuffers[i]));
- }
- }
-
+ this->resize(width, height);
// Create descriptor pool
VkDescriptorPoolSize pool_size = {
diff --git a/src/vulkan_swapchain.h b/src/vulkan_swapchain.h
index 99405b6..509753f 100644
--- a/src/vulkan_swapchain.h
+++ b/src/vulkan_swapchain.h
@@ -1,5 +1,4 @@
#include "imgui_impl_glfw.h"
-#include "imgui_impl_vulkan.h"
#include "vulkan_helper.h"
#include "vulkan/vulkan_core.h"
#include <cstdint>
@@ -12,7 +11,7 @@ std::vector<std::string> get_glfw_instance_extensions();
namespace iris {
struct Swapchain {
- iris::Device device;
+ Device device;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
@@ -21,12 +20,16 @@ struct Swapchain {
GLFWwindow *window = nullptr;
uint32_t width = -1;
uint32_t height = -1;
+ bool needs_recreate = false;
static constexpr uint32_t SWAPCHAIN_IMAGE_COUNT = 3;
VkImage swapchain_images[SWAPCHAIN_IMAGE_COUNT];
VkImageView swapchain_image_views[SWAPCHAIN_IMAGE_COUNT];
VkFramebuffer framebuffers[SWAPCHAIN_IMAGE_COUNT];
+ Texture2D upload_texture;
+
+ void resize(uint32_t new_width, uint32_t new_height);
Swapchain(GLFWwindow *window, iris::Device device);
~Swapchain();
};