aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2022-09-06 22:41:00 +0200
committerladevieq <ladevie.quentin@gmail.com>2022-09-06 22:41:00 +0200
commitb0708f165601fad16aa59715dbe32796a6e7081e (patch)
tree7741e0fd5e180905618d27ac4003c74633b96a13
parent24b02adbf6189025c00d62417fb4b49346f22c98 (diff)
Setup for texture upload system
-rw-r--r--CMakeLists.txt19
-rw-r--r--include/gltf.hpp9
-rw-r--r--include/material.hpp13
-rw-r--r--include/mesh.hpp6
-rw-r--r--include/vk-api.hpp13
-rw-r--r--include/vk-context.hpp21
-rw-r--r--include/vk-renderer.hpp113
-rw-r--r--src/CMakeLists.txt27
-rw-r--r--src/gltf.cpp47
-rw-r--r--src/main.cpp2
-rw-r--r--src/mesh.cpp4
-rw-r--r--src/vk-api.cpp125
-rw-r--r--src/vk-context.cpp76
-rw-r--r--src/vk-renderer.cpp148
14 files changed, 328 insertions, 295 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7fa8039..1180fe7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,31 +5,14 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file")
-set(CMAKE_BUILD_TYPE Debug)
+set(CMAKE_BUILD_TYPE Release)
project(path-tracer VERSION 1.0 LANGUAGES CXX)
-if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-add_compile_options(
- # -fsanitize=address TODO: Enable once compilation with the flag work on windows
- -fcolor-diagnostics -fansi-escape-codes # colored output when using ninja
- -ftime-trace
- -msse4.1
- # https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang
- -Wall
- -Wextra
- -Wshadow
- -Wcast-align
- -Wnon-virtual-dtor
- -Wpedantic
- -Wunused
-)
-endif()
find_package(imgui CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(Vulkan REQUIRED)
-find_package(Tracy CONFIG REQUIRED)
find_package(Threads REQUIRED)
if(UNIX AND NOT APPLE)
diff --git a/include/gltf.hpp b/include/gltf.hpp
index 2886dea..59189d4 100644
--- a/include/gltf.hpp
+++ b/include/gltf.hpp
@@ -15,6 +15,13 @@ struct node {
Mesh* mesh = nullptr;
};
+struct raw_image {
+ int32_t x;
+ int32_t y;
+ int32_t n;
+ uint8_t *data;
+};
+
namespace std::filesystem {
class path;
}
@@ -42,7 +49,7 @@ private:
json gltf_json;
std::vector<Mesh> meshes;
std::vector<material> materials;
- std::vector<texture> textures;
+ std::vector<Texture*> textures;
std::vector<std::vector<uint8_t>> buffers;
};
diff --git a/include/material.hpp b/include/material.hpp
index efa6141..5ac08f1 100644
--- a/include/material.hpp
+++ b/include/material.hpp
@@ -1,11 +1,12 @@
-#ifndef __MATERIAL_HPP_
-#define __MATERIAL_HPP_
+#pragma once
#include <cstdint>
#include "vec3.hpp"
-struct texture {
+class Texture;
+
+struct gpu_texture {
uint32_t image_id;
uint32_t sampler_id;
uint32_t padding[2];
@@ -13,10 +14,8 @@ struct texture {
struct material {
color base_color;
- texture base_color_texture;
- texture metallic_roughness_texture;
+ Texture* base_color_texture;
+ Texture* metallic_roughness_texture;
float metalness = 1.f;
float roughness = 1.f;
};
-
-#endif // !__MATERIAL_HPP_
diff --git a/include/mesh.hpp b/include/mesh.hpp
index b95c2a8..9a30be6 100644
--- a/include/mesh.hpp
+++ b/include/mesh.hpp
@@ -20,7 +20,7 @@ class Mesh {
uint32_t vertex_offset;
uint32_t index_offset;
size_t element_count;
- uint32_t mat_id;
+ material& material;
};
public:
@@ -39,14 +39,14 @@ public:
std::array<attribute, ATTRIBUTE_TYPE::MAX_ATTRIBUTE> attributes;
uint32_t vertex_count = 0;
uint32_t index_count = 0;
- // material& mat;
+ // material& material;
};
Mesh() = default;
[[nodiscard]] mesh_instance instantiate () const;
- void add_submesh(const submesh& submesh);
+ void add_submesh(const submesh& submesh, material& material);
static inline uint32_t attribute_components(enum ATTRIBUTE_TYPE attribute_type) {
switch(attribute_type) {
diff --git a/include/vk-api.hpp b/include/vk-api.hpp
index 2b88e42..6baaa73 100644
--- a/include/vk-api.hpp
+++ b/include/vk-api.hpp
@@ -140,8 +140,9 @@ class vkapi {
void destroy_sampler(handle sampler);
- std::vector<VkCommandBuffer> create_command_buffers(size_t command_buffers_count);
- void destroy_command_buffers(std::vector<VkCommandBuffer> &command_buffers);
+ [[nodiscard]] VkCommandPool create_command_pool() const;
+
+ void allocate_command_buffers(VkCommandPool command_pool, VkCommandBuffer* command_buffers, size_t count) const;
VkRenderPass create_render_pass(std::vector<VkFormat>& color_attachments_format, VkImageLayout initial_layout, VkImageLayout final_layout);
@@ -160,10 +161,6 @@ class vkapi {
void destroy_pipeline(pipeline &pipeline) const;
- std::vector<VkDescriptorSet> create_descriptor_sets(VkDescriptorSetLayout descriptor_sets_layout, size_t descriptor_sets_count);
- void destroy_descriptor_sets(std::vector<VkDescriptorSet> &descriptor_sets);
-
-
VkSurfaceKHR create_surface(window& wnd) const;
void destroy_surface(VkSurfaceKHR surface);
@@ -195,7 +192,8 @@ class vkapi {
void end_record(VkCommandBuffer command_buffer);
- VkResult submit(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const;
+ VkResult submit_graphics(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const;
+ VkResult submit_copy(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const;
VkResult present(swapchain& swapchain, uint32_t image_index, VkSemaphore wait_semaphore) const;
@@ -216,7 +214,6 @@ class vkapi {
std::vector<image*> images;
std::vector<sampler*> samplers;
- VkCommandPool command_pool;
VkDescriptorPool descriptor_pool;
};
diff --git a/include/vk-context.hpp b/include/vk-context.hpp
index 8d0b91f..58d7ce9 100644
--- a/include/vk-context.hpp
+++ b/include/vk-context.hpp
@@ -1,11 +1,15 @@
-#ifndef __VK_CONTEXT_HPP_
-#define __VK_CONTEXT_HPP_
+#pragma once
-#include <vector>
#include "vulkan-loader.hpp"
using VmaAllocator = struct VmaAllocator_T*;
+struct queue {
+ VkQueue handle;
+ uint32_t index;
+ VkQueueFlags usages;
+};
+
class vkcontext {
public:
vkcontext();
@@ -19,8 +23,7 @@ class vkcontext {
VmaAllocator allocator;
- uint32_t queue_index;
- VkQueue queue;
+ queue graphics_queue;
private:
void create_instance();
@@ -33,16 +36,14 @@ class vkcontext {
void select_physical_device();
- void select_queue(VkQueueFlags queueUsage);
+ [[nodiscard]] uint32_t select_queue(VkQueueFlags queue_usage) const;
- static void check_available_instance_layers(std::vector<const char*>& needed_layers);
+ static void check_available_instance_layers(const char* needed_layers[], size_t needed_layers_count);
- static void check_available_instance_extensions(std::vector<const char*>& needed_extensions);
+ static void check_available_instance_extensions(const char* needed_extensions[], size_t needed_extensions_count);
static bool support_required_features(VkPhysicalDevice physical_device);
VkDebugUtilsMessengerEXT debugMessenger;
};
-
-#endif // !__VK_CONTEXT_HPP_
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
index 827445f..ca4c261 100644
--- a/include/vk-renderer.hpp
+++ b/include/vk-renderer.hpp
@@ -17,6 +17,7 @@ class window;
class Texture;
class Buffer;
class Sampler;
+class RingBuffer;
class vkrenderer {
public:
@@ -24,24 +25,20 @@ class vkrenderer {
~vkrenderer();
- void begin_frame();
-
- void finish_frame();
-
void recreate_swapchain();
- void update_image(Texture* texture, void* data);
static Buffer* create_buffer(size_t size);
static Buffer* create_index_buffer(size_t size);
- static Texture* create_2d_texture(size_t width, size_t height, VkFormat format);
+ static Texture* create_2d_texture(size_t width, size_t height, VkFormat format, Sampler *sampler = nullptr);
static void destroy_2d_texture(Texture* texture);
static Sampler* create_sampler(VkFilter filter, VkSamplerAddressMode address_mode);
+
ComputeRenderpass* create_compute_renderpass();
PrimitiveRenderpass* create_primitive_renderpass();
@@ -50,6 +47,8 @@ class vkrenderer {
void render();
+ RingBuffer* get_staging_buffer() { return staging_buffer; }
+
[[nodiscard]]uint32_t frame_index() const { return this->virtual_frame_index; }
[[nodiscard]]Texture* back_buffer() const { return swapchain_textures[swapchain_image_index]; }
@@ -64,18 +63,23 @@ class vkrenderer {
private:
- void handle_swapchain_result(VkResult function_result);
+ void begin_frame();
+
+ void finish_frame();
+
- // vkapi api;
+ void handle_swapchain_result(VkResult function_result);
std::vector<Renderpass*> renderpasses;
+ static constexpr uint32_t initial_copy_command_buffers = 10U;
uint32_t virtual_frame_index = 0;
uint32_t swapchain_image_index = 0;
- std::vector<VkCommandBuffer> command_buffers;
+ VkCommandBuffer graphics_command_buffers[virtual_frames_count];
+ std::vector<VkCommandBuffer> copy_command_buffers[virtual_frames_count];
- handle staging_buffer;
+ RingBuffer* staging_buffer;
pipeline tonemapping_pipeline;
@@ -84,6 +88,9 @@ class vkrenderer {
VkSemaphore execution_semaphores[virtual_frames_count];
VkSemaphore acquire_semaphores[virtual_frames_count];
+ VkCommandPool graphics_command_pool;
+ VkCommandPool copy_command_pools[virtual_frames_count];
+
VkSurfaceKHR platform_surface;
swapchain swapchain;
std::vector<Texture*> swapchain_textures;
@@ -91,13 +98,34 @@ class vkrenderer {
const uint32_t min_swapchain_image_count = 3;
};
-// TODO: Move those to there own files
-class Texture {
+class RingBuffer {
public:
+ RingBuffer(size_t size)
+ : buffer_size(size) {}
- sampler sampler;
+ [[nodiscard]]size_t alloc(size_t alloc_size) const {
+ assert(alloc_size > 0);
- handle device_image;
+ if (ptr + alloc_size < buffer_size) {
+ return ptr;
+ }
+ return 0;
+ }
+
+ void write(void* data, off_t alloc_offset, size_t data_size) const {
+ auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
+
+ std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
+ }
+
+ void reset() {
+ ptr = 0;
+ }
+
+ handle device_buffer;
+
+ size_t buffer_size;
+ off_t ptr;
};
class Sampler {
@@ -106,33 +134,55 @@ class Sampler {
handle device_sampler;
};
-class Buffer {
+// TODO: Move those to there own files
+class Texture {
public:
- Buffer(size_t size);
+ void write(void* data) const {
+ auto image = vkrenderer::api.get_image(device_image);
+ auto texture_size = image.size.width * image.size.height * 4;
- ~Buffer() {
- vkrenderer::api.destroy_buffer(device_buffer);
- }
+ // TODO: Do all this inside vkrenderer
+ // auto* buffer = vkrenderer::get_staging_buffer();
+ // auto alloc_offset = buffer->alloc(texture_size);
+ // assert(alloc_offset > 0);
- void write(void* data, off_t alloc_offset, size_t data_size) const {
- auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
+ // // std::memcpy(buffer.device_ptr, data, texture_size);
+ // buffer->write(data, alloc_offset, texture_size);
- std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
+ // vkrenderer::api.create_command_buffers
+ // submit upload work
+ // VKRESULT(vkWaitForFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
+ // VKRESULT(vkResetFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index]))
+
+ // auto* cmd_buf = command_buffers[virtual_frame_index];
+ // api.start_record(cmd_buf);
+
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, device_image);
+
+ // api.copy_buffer(cmd_buf, buffer, device_image);
+
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, device_image);
+
+ // api.end_record(cmd_buf);
+
+
+
+ // VKRESULT(vkWaitForFences(vkrenderer::context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
}
- handle device_buffer;
+ Sampler* sampler = nullptr;
- size_t buffer_size;
+ handle device_image;
};
-class RingBuffer {
+class Buffer {
public:
- RingBuffer(size_t size)
- : buffer_size(size) {}
- [[nodiscard]]bool alloc(size_t alloc_size) const {
- return ptr + alloc_size > buffer_size;
+ Buffer(size_t size);
+
+ ~Buffer() {
+ vkrenderer::api.destroy_buffer(device_buffer);
}
void write(void* data, off_t alloc_offset, size_t data_size) const {
@@ -141,14 +191,9 @@ class RingBuffer {
std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
}
- void reset() {
- ptr = 0;
- }
-
handle device_buffer;
size_t buffer_size;
- off_t ptr;
};
#endif // !__VK_RENDERER_HPP_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b56a871..54a4c54 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LIBRARIES imgui::imgui nlohmann_json::nlohmann_json Tracy::TracyClient)
+set(LIBRARIES imgui::imgui)
set(DEFINES -DNOMINMAX -D_USE_MATH_DEFINES -DVK_NO_PROTOTYPES)
@@ -29,9 +29,31 @@ add_executable(
primitive-renderpass.cpp
bvh.cpp
mesh.cpp
- # ${Tracy_SOURCE_DIR}/TracyClient.cpp
)
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ target_compile_options(
+ path-tracer
+ PRIVATE
+ # -fsanitize=address TODO: enable once compiling with the flag works
+ -fcolor-diagnostics -fansi-escape-codes # colored output when using ninja
+ -ftime-trace
+ -msse4.1
+ # https://github.com/cpp-best-practices/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#gcc--clang
+ -Wall
+ -Wextra
+ -Wshadow
+ -Wcast-align
+ -Wnon-virtual-dtor
+ -Wpedantic
+ -Wunused
+ )
+
+# target_link_options(path-tracer PRIVATE -fsanitize=address)
+endif()
+
+target_link_directories(path-tracer PRIVATE "C:\\Program Files\\LLVM\\lib\\clang\\14.0.6\\lib\\windows")
+
target_compile_definitions(path-tracer PUBLIC ${DEFINES})
target_include_directories(path-tracer SYSTEM PUBLIC ${CMAKE_SOURCE_DIR}/thirdparty)
@@ -43,7 +65,6 @@ if(UNIX AND NOT APPLE)
target_include_directories(path-tracer PUBLIC ${X11_xcb_INCLUDE_PATH})
endif()
-
if(UNIX AND NOT APPLE)
list(APPEND LIBRARIES ${CMAKE_DL_LIBS} ${X11_xcb_LIB} ${X11_xkbcommon_LIB} ${X11_xkbcommon_X11_LIB})
endif()
diff --git a/src/gltf.cpp b/src/gltf.cpp
index a05237c..59094d9 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -18,10 +18,11 @@ gltf::gltf(const std::filesystem::path &filepath) {
auto& scene = gltf_json["scenes"][0];
auto &gltf_buffers = gltf_json["buffers"];
- buffers.reserve(gltf_buffers.size());
- for (auto& gltf_buffer : gltf_buffers) {
- auto buffer_path = parent_path / gltf_buffer["uri"].get<std::string>();
- buffers.emplace_back(read_file(buffer_path.string().c_str()));
+ auto buffer_count = gltf_buffers.size();
+ buffers.resize(gltf_buffers.size());
+ for (auto buffer_index { 0U }; buffer_index < buffer_count; buffer_index++) {
+ auto buffer_path = parent_path / gltf_buffers[buffer_index]["uri"].get<std::string>();
+ buffers[buffer_index] = read_file(buffer_path.string().c_str());
}
load_textures(parent_path);
@@ -68,7 +69,8 @@ void gltf::load_meshes() {
const auto &primitives = gltf_meshes[mesh_index]["primitives"];
for (const auto &primitive : primitives) {
- mesh.add_submesh(load_primitive(primitive));
+ auto material = materials[primitive["material"].get<uint32_t>()];
+ mesh.add_submesh(load_primitive(primitive), material);
}
Mesh::register_mesh(mesh);
@@ -91,7 +93,6 @@ Mesh::submesh gltf::load_primitive(const json &primitive) {
submesh.index_count = gltf_json["accessors"][primitive["indices"].get<uint32_t>()]["count"].get<uint32_t>();
submesh.vertex_count = gltf_json["accessors"][primitive["attributes"]["POSITION"].get<uint32_t>()]["count"].get<uint32_t>();
- // submesh.mat = materials[gltf_primitive["material"].get<uint32_t>()];
return submesh;
}
@@ -111,22 +112,13 @@ Mesh::attribute gltf::load_attribute(uint32_t accessor_index) {
void gltf::load_textures(const std::filesystem::path &path) {
const auto &gltf_images = gltf_json["images"];
auto images_count = gltf_images.size();
- std::vector<Texture *> images{images_count};
+ std::vector<raw_image> images{images_count};
for (size_t image_index = 0; image_index < images_count; image_index++) {
const auto &gltf_image = gltf_images[image_index];
- int x;
- int y;
- int n;
auto filepath = (path / gltf_image["uri"].get<std::string>()).string();
- unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4);
- auto *img = vkrenderer::create_2d_texture(static_cast<uint32_t>(x), static_cast<uint32_t>(y), VK_FORMAT_R8G8B8A8_UNORM);
-
- // renderer.update_image(img, data);
-
- stbi_image_free(data);
-
- images[image_index] = img;
+ auto& image = images[image_index];
+ image.data = stbi_load(filepath.c_str(), &image.x, &image.y, &image.n, 4);
}
const auto &gltf_samplers = gltf_json["samplers"];
@@ -144,19 +136,20 @@ void gltf::load_textures(const std::filesystem::path &path) {
for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
auto gltf_texture = gltf_textures[texture_index];
- auto image_index = gltf_texture["source"].get<uint32_t>();
- auto &image = images[image_index];
-
- uint32_t image_id = vkrenderer::api.get_image(image->device_image).bindless_sampled_index;
- uint32_t sampler_id = 0;
+ auto& image = images[gltf_texture["source"].get<uint32_t>()];
+ Sampler *sampler = nullptr;
if (gltf_texture.contains("sampler")) {
auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
- auto &sampler = samplers[sampler_index];
- sampler_id = vkrenderer::api.get_sampler(sampler->device_sampler).bindless_index;
+ sampler = samplers[sampler_index];
}
- textures[texture_index] =
- texture{.image_id = image_id, .sampler_id = sampler_id};
+ auto *texture = vkrenderer::create_2d_texture(static_cast<uint32_t>(image.x), static_cast<uint32_t>(image.y), VK_FORMAT_R8G8B8A8_UNORM, sampler);
+
+ texture->write(image.data);
+
+ stbi_image_free(image.data);
+
+ textures[texture_index] = texture;
}
}
diff --git a/src/main.cpp b/src/main.cpp
index 58882d3..5e39a09 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,8 +14,6 @@
#include "window.hpp"
#include "utils.hpp"
-#include "Tracy.hpp"
-
#if defined(LINUX)
#include <dlfcn.h>
#include <unistd.h>
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 191aaf7..b3916aa 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -2,13 +2,13 @@
static std::vector<Mesh> meshes {};
-void Mesh::add_submesh(const submesh& submesh) {
+void Mesh::add_submesh(const submesh& submesh, material& material) {
submeshes.emplace_back(
submesh_info {
(uint32_t)vertex_count,
(uint32_t)index_count,
submesh.index_count / 3,
- 0
+ material
}
);
diff --git a/src/vk-api.cpp b/src/vk-api.cpp
index ebffd38..81242a5 100644
--- a/src/vk-api.cpp
+++ b/src/vk-api.cpp
@@ -20,15 +20,7 @@
vkapi::vkapi(vkcontext& context)
: context(context) {
- VkCommandPoolCreateInfo cmd_pool_create_info = {};
- cmd_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- cmd_pool_create_info.pNext = nullptr;
- cmd_pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- cmd_pool_create_info.queueFamilyIndex = context.queue_index;
-
- VKRESULT(vkCreateCommandPool(context.device, &cmd_pool_create_info, nullptr, &command_pool))
-
- std::vector<VkDescriptorPoolSize> descriptor_pools_sizes = {
+ VkDescriptorPoolSize descriptor_pools_sizes[] = {
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = (uint32_t)global_descriptor::pool_size,
@@ -52,8 +44,8 @@ vkapi::vkapi(vkcontext& context)
descriptor_pool_create_info.pNext = nullptr;
descriptor_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
descriptor_pool_create_info.maxSets = 0xff;
- descriptor_pool_create_info.poolSizeCount = descriptor_pools_sizes.size();
- descriptor_pool_create_info.pPoolSizes = descriptor_pools_sizes.data();
+ descriptor_pool_create_info.poolSizeCount = sizeof(descriptor_pools_sizes) / sizeof(descriptor_pools_sizes[0]);
+ descriptor_pool_create_info.pPoolSizes = descriptor_pools_sizes;
VKRESULT(vkCreateDescriptorPool(context.device, &descriptor_pool_create_info, nullptr, &descriptor_pool))
@@ -146,6 +138,7 @@ vkapi::vkapi(vkcontext& context)
}
vkapi::~vkapi() {
+ // Free resources
for (handle buffer_handle = 0; buffer_handle < buffers.size(); buffer_handle++) {
destroy_buffer(buffer_handle);
}
@@ -163,7 +156,6 @@ vkapi::~vkapi() {
vkDestroyPipelineLayout(context.device, bindless_descriptor.pipeline_layout, nullptr);
vkFreeDescriptorSets(context.device, descriptor_pool, 1, &bindless_descriptor.set);
- vkDestroyCommandPool(context.device, command_pool, nullptr);
vkDestroyDescriptorPool(context.device, descriptor_pool, nullptr);
}
@@ -309,8 +301,14 @@ handle vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags u
}
void vkapi::destroy_image(handle image) {
auto* current_image = images[image];
- bindless_descriptor.free(current_image->bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- bindless_descriptor.free(current_image->bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+
+ if (current_image->bindless_storage_index != 0U) {
+ bindless_descriptor.free(current_image->bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ }
+
+ if (current_image->bindless_sampled_index != 0U) {
+ bindless_descriptor.free(current_image->bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ }
vmaDestroyImage(context.allocator, current_image->handle, current_image->alloc);
vkDestroyImageView(context.device, current_image->view, nullptr);
@@ -437,7 +435,7 @@ handle vkapi::create_sampler(VkFilter filter, VkSamplerAddressMode address_mode)
}
void vkapi::destroy_sampler(handle sampler) {
- auto current_sampler = samplers[sampler];
+ auto* current_sampler = samplers[sampler];
bindless_descriptor.free(current_sampler->bindless_index, VK_DESCRIPTOR_TYPE_SAMPLER);
vkDestroySampler(context.device, current_sampler->handle, VK_NULL_HANDLE);
@@ -446,25 +444,31 @@ void vkapi::destroy_sampler(handle sampler) {
}
-std::vector<VkCommandBuffer> vkapi::create_command_buffers(size_t command_buffers_count) {
+VkCommandPool vkapi::create_command_pool() const {
+ VkCommandPoolCreateInfo cmd_pool_create_info = {};
+ cmd_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ cmd_pool_create_info.pNext = nullptr;
+ cmd_pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ cmd_pool_create_info.queueFamilyIndex = context.graphics_queue.index;
+
+ VkCommandPool command_pool;
+ VKRESULT(vkCreateCommandPool(context.device, &cmd_pool_create_info, nullptr, &command_pool))
+
+ return command_pool;
+}
+
+
+void vkapi::allocate_command_buffers(VkCommandPool command_pool, VkCommandBuffer* command_buffers, size_t count) const {
VkCommandBufferAllocateInfo cmd_buf_allocate_info = {};
cmd_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmd_buf_allocate_info.pNext = VK_NULL_HANDLE;
cmd_buf_allocate_info.commandPool = command_pool;
cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- cmd_buf_allocate_info.commandBufferCount = command_buffers_count;
+ cmd_buf_allocate_info.commandBufferCount = count;
- std::vector<VkCommandBuffer> command_buffers { command_buffers_count };
- vkAllocateCommandBuffers(context.device, &cmd_buf_allocate_info, command_buffers.data());
-
- return command_buffers;
+ vkAllocateCommandBuffers(context.device, &cmd_buf_allocate_info, command_buffers);
}
-void vkapi::destroy_command_buffers(std::vector<VkCommandBuffer> &command_buffers) {
- vkFreeCommandBuffers(context.device, command_pool, command_buffers.size(), command_buffers.data());
-}
-
-
// TODO: attachment structure
VkRenderPass vkapi::create_render_pass(std::vector<VkFormat>& color_attachments_format, VkImageLayout initial_layout, VkImageLayout final_layout) {
std::vector<VkAttachmentDescription> attachments_description = {};
@@ -621,7 +625,7 @@ pipeline vkapi::create_compute_pipeline(const char* shader_name) const {
auto shader_filename = std::string(shader_name) + ".comp.spv";
auto shader_path = std::filesystem::path{ "./shaders" } / shader_filename;
- std::vector<uint8_t> shader_code = read_file(shader_path.string().c_str());
+ auto shader_code = read_file(shader_path.string().c_str());
assert(!shader_code.empty());
pipeline.shader_modules.resize(1);
@@ -799,27 +803,6 @@ void vkapi::destroy_pipeline(pipeline &pipeline) const {
}
-std::vector<VkDescriptorSet> vkapi::create_descriptor_sets(VkDescriptorSetLayout descriptor_sets_layout, size_t descriptor_sets_count) {
- std::vector<VkDescriptorSetLayout> sets_layouts = { descriptor_sets_count, descriptor_sets_layout };
-
- VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {};
- descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- descriptor_set_allocate_info.pNext = nullptr;
- descriptor_set_allocate_info.descriptorPool = descriptor_pool;
- descriptor_set_allocate_info.descriptorSetCount = sets_layouts.size();
- descriptor_set_allocate_info.pSetLayouts = sets_layouts.data();
-
- std::vector<VkDescriptorSet> descriptor_sets { descriptor_sets_count };
- vkAllocateDescriptorSets(context.device, &descriptor_set_allocate_info, descriptor_sets.data());
-
- return descriptor_sets;
-}
-
-void vkapi::destroy_descriptor_sets(std::vector<VkDescriptorSet> &descriptor_sets) {
- vkFreeDescriptorSets(context.device, descriptor_pool, descriptor_sets.size(), descriptor_sets.data());
-}
-
-
VkSurfaceKHR vkapi::create_surface(window& wnd) const {
VkSurfaceKHR surface;
@@ -863,7 +846,7 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
swapchain swapchain;
VkBool32 queue_support_presentation = VK_FALSE;
- VKRESULT(vkGetPhysicalDeviceSurfaceSupportKHR(context.physical_device, context.queue_index, surface, &queue_support_presentation))
+ VKRESULT(vkGetPhysicalDeviceSurfaceSupportKHR(context.physical_device, context.graphics_queue.index, surface, &queue_support_presentation))
assert(queue_support_presentation == VK_TRUE);
@@ -944,7 +927,7 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
};
for (size_t image_index = 0; image_index < swapchain.image_count; image_index++) {
- struct image* current_image = new struct image();
+ auto* current_image = new struct image();
current_image->handle = vk_images[image_index];
current_image->size = image_size;
@@ -973,12 +956,12 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
auto current_image_handle = images.size() - 1;
- if (usages & VK_IMAGE_USAGE_STORAGE_BIT) {
+ if ((usages & VK_IMAGE_USAGE_STORAGE_BIT) != 0U) {
current_image->bindless_storage_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
update_descriptor_image(current_image_handle, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
}
- if (usages & VK_IMAGE_USAGE_SAMPLED_BIT) {
+ if ((usages & VK_IMAGE_USAGE_SAMPLED_BIT) != 0U) {
current_image->bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
update_descriptor_image(current_image_handle, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
}
@@ -1117,19 +1100,19 @@ void vkapi::start_record(VkCommandBuffer command_buffer) {
}
void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, handle image) {
- auto current_image = images[image];
+ auto *current_image = images[image];
- VkImageMemoryBarrier undefined_to_general_barrier = {};
- undefined_to_general_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- undefined_to_general_barrier.pNext = nullptr;
- undefined_to_general_barrier.srcAccessMask = current_image->previous_access;
- undefined_to_general_barrier.dstAccessMask = dst_access;
- undefined_to_general_barrier.oldLayout = current_image->previous_layout;
- undefined_to_general_barrier.newLayout = dst_layout;
- undefined_to_general_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- undefined_to_general_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- undefined_to_general_barrier.image = current_image->handle;
- undefined_to_general_barrier.subresourceRange = current_image->subresource_range;
+ VkImageMemoryBarrier image_barrier = {};
+ image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ image_barrier.pNext = nullptr;
+ image_barrier.srcAccessMask = current_image->previous_access;
+ image_barrier.dstAccessMask = dst_access;
+ image_barrier.oldLayout = current_image->previous_layout;
+ image_barrier.newLayout = dst_layout;
+ image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ image_barrier.image = current_image->handle;
+ image_barrier.subresourceRange = current_image->subresource_range;
vkCmdPipelineBarrier(
command_buffer,
@@ -1141,7 +1124,7 @@ void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layo
0,
nullptr,
1,
- &undefined_to_general_barrier
+ &image_barrier
);
current_image->previous_layout = dst_layout;
@@ -1242,21 +1225,21 @@ void vkapi::end_record(VkCommandBuffer command_buffer) {
VKRESULT(vkEndCommandBuffer(command_buffer))
}
-VkResult vkapi::submit(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const {
+VkResult vkapi::submit_graphics(VkCommandBuffer command_buffer, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const {
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = nullptr;
- submit_info.waitSemaphoreCount = wait_semaphore ? 1 : 0;
+ submit_info.waitSemaphoreCount = wait_semaphore != nullptr ? 1 : 0;
submit_info.pWaitSemaphores = &wait_semaphore;
- submit_info.pWaitDstStageMask = wait_semaphore ? &wait_stage : VK_NULL_HANDLE;
- submit_info.signalSemaphoreCount = signal_semaphore ? 1 : 0;
+ submit_info.pWaitDstStageMask = wait_semaphore != nullptr ? &wait_stage : VK_NULL_HANDLE;
+ submit_info.signalSemaphoreCount = signal_semaphore != nullptr ? 1 : 0;
submit_info.pSignalSemaphores = &signal_semaphore;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer;
- return vkQueueSubmit(context.queue, 1, &submit_info, submission_fence);
+ return vkQueueSubmit(context.graphics_queue.handle, 1, &submit_info, submission_fence);
}
VkResult vkapi::present(swapchain& swapchain, uint32_t image_index, VkSemaphore wait_semaphore) const {
@@ -1270,7 +1253,7 @@ VkResult vkapi::present(swapchain& swapchain, uint32_t image_index, VkSemaphore
present_info.pImageIndices = &image_index;
present_info.pResults = nullptr;
- return vkQueuePresentKHR(context.queue, &present_info);
+ return vkQueuePresentKHR(context.graphics_queue.handle, &present_info);
}
diff --git a/src/vk-context.cpp b/src/vk-context.cpp
index 2783c6a..e4a8815 100644
--- a/src/vk-context.cpp
+++ b/src/vk-context.cpp
@@ -2,6 +2,8 @@
#include <iostream>
#include <cassert>
+#include <vector>
+#include <array>
#define VMA_IMPLEMENTATION
#include <vk_mem_alloc.h>
@@ -83,15 +85,16 @@ void vkcontext::create_instance() {
app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
app_info.apiVersion = VK_API_VERSION_1_2;
- std::vector<const char*> needed_layers = {
+ const char* needed_layers[] = {
#if defined(_DEBUG)
"VK_LAYER_KHRONOS_validation",
#endif
};
+ auto needed_layers_count = sizeof(needed_layers) / sizeof(needed_layers[0]);
- check_available_instance_layers(needed_layers);
+ check_available_instance_layers(needed_layers, needed_layers_count);
- std::vector<const char*> needed_extensions = {
+ const char* needed_extensions[] = {
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
"VK_KHR_surface",
#if defined(LINUX)
@@ -102,16 +105,17 @@ void vkcontext::create_instance() {
"VK_EXT_metal_surface"
#endif
};
+ auto needed_extensions_count = sizeof(needed_extensions) / sizeof(needed_extensions[0]);
- check_available_instance_extensions(needed_extensions);
+ check_available_instance_extensions(needed_extensions, needed_extensions_count);
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pApplicationInfo = &app_info;
- instance_create_info.enabledLayerCount = needed_layers.size();
- instance_create_info.ppEnabledLayerNames = needed_layers.data();
- instance_create_info.enabledExtensionCount = needed_extensions.size();
- instance_create_info.ppEnabledExtensionNames = needed_extensions.data();
+ instance_create_info.enabledLayerCount = needed_layers_count;
+ instance_create_info.ppEnabledLayerNames = needed_layers;
+ instance_create_info.enabledExtensionCount = needed_extensions_count;
+ instance_create_info.ppEnabledExtensionNames = needed_extensions;
VKRESULT(vkCreateInstance(&instance_create_info, nullptr, &instance))
@@ -142,15 +146,19 @@ void vkcontext::create_debugger() {
void vkcontext::create_device() {
select_physical_device();
- select_queue(VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT);
- VkDeviceQueueCreateInfo queue_create_info = {};
- queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queue_create_info.queueFamilyIndex = queue_index;
- queue_create_info.queueCount = 1;
+ graphics_queue = {
+ .usages = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT,
+ };
+ auto queue_priority = 1.f;
+ graphics_queue.index = select_queue(graphics_queue.usages);
+ auto queue_create_info = VkDeviceQueueCreateInfo {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ .queueFamilyIndex = graphics_queue.index,
+ .queueCount = 1,
- float queue_priority = 1.f;
- queue_create_info.pQueuePriorities = &queue_priority;
+ .pQueuePriorities = &queue_priority
+ };
VkPhysicalDeviceVulkan12Features physical_device_12_features = {};
physical_device_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
@@ -168,7 +176,7 @@ void vkcontext::create_device() {
device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
device_features.pNext = &physical_device_12_features;
- std::vector<const char*> device_ext = {
+ const char* device_ext[] = {
"VK_KHR_swapchain",
};
@@ -177,15 +185,15 @@ void vkcontext::create_device() {
device_create_info.pNext = &device_features;
device_create_info.pQueueCreateInfos = &queue_create_info;
device_create_info.queueCreateInfoCount = 1;
- device_create_info.ppEnabledExtensionNames = device_ext.data();
- device_create_info.enabledExtensionCount = device_ext.size();
+ device_create_info.ppEnabledExtensionNames = device_ext;
+ device_create_info.enabledExtensionCount = sizeof(device_ext) / sizeof(device_ext[0]);
device_create_info.enabledLayerCount = 0; // Deprecated https://www.khronos.org/registry/vulkan/specs/1.2/html/chap31.html#extendingvulkan-layers-devicelayerdeprecation
VKRESULT(vkCreateDevice(physical_device, &device_create_info, nullptr, &device))
load_device_functions(device);
- vkGetDeviceQueue(device, queue_index, 0, &queue);
+ vkGetDeviceQueue(device, graphics_queue.index, 0, &graphics_queue.handle);
std::cerr << "Device ready" << std::endl;
}
@@ -208,7 +216,6 @@ void vkcontext::select_physical_device() {
if (physical_devices_count < 1) {
std::cerr << "No physical device found !" << std::endl;
- exit(1);
}
std::vector<VkPhysicalDevice> physical_devices { physical_devices_count };
@@ -224,7 +231,7 @@ void vkcontext::select_physical_device() {
assert(physical_device != VK_NULL_HANDLE);
}
-void vkcontext::select_queue(VkQueueFlags queueUsage) {
+uint32_t vkcontext::select_queue(VkQueueFlags queue_usage) const {
uint32_t queue_properties_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr);
@@ -232,17 +239,16 @@ void vkcontext::select_queue(VkQueueFlags queueUsage) {
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data());
for (uint32_t properties_index = 0; properties_index < queue_properties_count; properties_index++) {
- if ((queue_properties[properties_index].queueFlags & queueUsage) != 0U) {
- queue_index = properties_index;
- return;
+ if ((queue_properties[properties_index].queueFlags & queue_usage) != 0U) {
+ return properties_index;
}
}
- std::cerr << "No compute queue found !" << std::endl;
- exit(1);
+ assert(true);
+ return UINT_MAX;
}
-void vkcontext::check_available_instance_layers(std::vector<const char*>& needed_layers) {
+void vkcontext::check_available_instance_layers(const char* needed_layers[], size_t needed_layers_count) {
uint32_t property_count = 0;
vkEnumerateInstanceLayerProperties(&property_count, VK_NULL_HANDLE);
@@ -251,18 +257,18 @@ void vkcontext::check_available_instance_layers(std::vector<const char*>& needed
uint32_t available_needed_layers_count = 0;
- for (auto& layer_property: layer_properties) {
- for (auto& needed_layer: needed_layers) {
- if (strcmp(layer_property.layerName, needed_layer) == 0) {
+ for (auto layer_property: layer_properties) {
+ for (auto layer_index { 0U }; layer_index < needed_layers_count; layer_index++) {
+ if (strcmp(layer_property.layerName, needed_layers[layer_index]) == 0) {
available_needed_layers_count++;
}
}
}
- assert(available_needed_layers_count == needed_layers.size());
+ assert(available_needed_layers_count == needed_layers_count);
}
-void vkcontext::check_available_instance_extensions(std::vector<const char*>& needed_extensions) {
+void vkcontext::check_available_instance_extensions(const char* needed_extensions[], size_t needed_extensions_count) {
uint32_t vulkan_extensions_count = 0;
vkEnumerateInstanceExtensionProperties(VK_NULL_HANDLE, &vulkan_extensions_count, VK_NULL_HANDLE);
@@ -271,14 +277,14 @@ void vkcontext::check_available_instance_extensions(std::vector<const char*>& ne
uint32_t available_needed_extensions_count = 0;
for (auto& extension: vulkan_extensions_properties) {
- for (auto& needed_extension: needed_extensions) {
- if (strcmp(extension.extensionName, needed_extension) == 0) {
+ for (auto extension_index { 0U }; extension_index < needed_extensions_count; extension_index++) {
+ if (strcmp(extension.extensionName, needed_extensions[extension_index]) == 0) {
available_needed_extensions_count++;
}
}
}
- assert(available_needed_extensions_count == needed_extensions.size());
+ assert(available_needed_extensions_count == needed_extensions_count);
}
bool vkcontext::support_required_features(VkPhysicalDevice physical_device) {
diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp
index 189ac33..91115ba 100644
--- a/src/vk-renderer.cpp
+++ b/src/vk-renderer.cpp
@@ -18,8 +18,8 @@
#define VKRESULT(result) result;
#endif
-vkcontext vkrenderer::context = vkcontext();
-vkapi vkrenderer::api = vkapi(vkrenderer::context);
+auto vkrenderer::context = vkcontext();
+auto vkrenderer::api = vkapi(vkrenderer::context);
vkrenderer::vkrenderer(window& wnd) {
platform_surface = api.create_surface(wnd);
@@ -40,15 +40,21 @@ vkrenderer::vkrenderer(window& wnd) {
tonemapping_pipeline = api.create_compute_pipeline("tonemapping");
- command_buffers = api.create_command_buffers(virtual_frames_count);
+ graphics_command_pool = api.create_command_pool();
+ api.allocate_command_buffers(graphics_command_pool, graphics_command_buffers, virtual_frames_count);
for(size_t index { 0 }; index < virtual_frames_count; index++) {
submission_fences[index] = api.create_fence();
execution_semaphores[index] = api.create_semaphore();
acquire_semaphores[index] = api.create_semaphore();
+
+ copy_command_pools[index] = api.create_command_pool();
+ copy_command_buffers[index].resize(initial_copy_command_buffers);
+ api.allocate_command_buffers(copy_command_pools[index], copy_command_buffers[index].data(), copy_command_buffers[index].size());
}
- staging_buffer = api.create_buffer(4096 * 4096 * 4 * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
+
+ // staging_buffer = api.create_buffer(4096 * 4096 * 4 * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
}
vkrenderer::~vkrenderer() {
@@ -58,44 +64,28 @@ vkrenderer::~vkrenderer() {
delete renderpass;
}
+ for(size_t index { 0 }; index < virtual_frames_count; index++) {
+ vkFreeCommandBuffers(
+ context.device,
+ copy_command_pools[index],
+ copy_command_buffers[index].size(),
+ copy_command_buffers[index].data()
+ );
+ }
+
api.destroy_fences(submission_fences, virtual_frames_count);
api.destroy_semaphores(execution_semaphores, virtual_frames_count);
api.destroy_semaphores(acquire_semaphores, virtual_frames_count);
- api.destroy_command_buffers(command_buffers);
+ vkDestroyCommandPool(context.device, graphics_command_pool, nullptr);
+
+ vkFreeCommandBuffers(context.device, graphics_command_pool, virtual_frames_count, graphics_command_buffers);
api.destroy_pipeline(tonemapping_pipeline);
api.destroy_swapchain(swapchain);
api.destroy_surface(platform_surface);
}
-
-void vkrenderer::begin_frame() {
- VKRESULT(vkWaitForFences(context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
- VKRESULT(vkResetFences(context.device, 1, &submission_fences[virtual_frame_index]))
-
- swapchain_image_index = 0;
- auto acquire_result = vkAcquireNextImageKHR(context.device, swapchain.handle, UINT64_MAX, acquire_semaphores[virtual_frame_index], VK_NULL_HANDLE, &swapchain_image_index);
- handle_swapchain_result(acquire_result);
-
- api.start_record(command_buffers[virtual_frame_index]);
-}
-
-void vkrenderer::finish_frame() {
- auto* cmd_buf = command_buffers[virtual_frame_index];
-
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, swapchain.images[swapchain_image_index]);
-
- api.end_record(cmd_buf);
-
- api.submit(cmd_buf, acquire_semaphores[virtual_frame_index], execution_semaphores[virtual_frame_index], submission_fences[virtual_frame_index]);
-
- auto present_result = api.present(swapchain, swapchain_image_index, execution_semaphores[virtual_frame_index]);
- handle_swapchain_result(present_result);
-
- virtual_frame_index = ++virtual_frame_index % virtual_frames_count;
-}
-
void vkrenderer::recreate_swapchain() {
VKRESULT(vkWaitForFences(context.device, vkrenderer::virtual_frames_count, submission_fences, VK_TRUE, UINT64_MAX))
@@ -117,47 +107,12 @@ void vkrenderer::recreate_swapchain() {
}
}
-void vkrenderer::handle_swapchain_result(VkResult function_result) {
- switch(function_result) {
- case VK_ERROR_OUT_OF_DATE_KHR:
- return recreate_swapchain();
- case VK_ERROR_SURFACE_LOST_KHR:
- assert(true && "surface lost");
- default:
- return;
- }
-}
-
-void vkrenderer::update_image(Texture* texture, void* data) {
- auto image = api.get_image(texture->device_image);
- auto max_texture_size = image.size.width * image.size.height * 4;
- auto buffer = api.get_buffer(staging_buffer);
- if (buffer.size < max_texture_size) {
- api.destroy_buffer(staging_buffer);
-
- staging_buffer = api.create_buffer(max_texture_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
- }
-
- std::memcpy(buffer.device_ptr, data, max_texture_size);
-
- VKRESULT(vkWaitForFences(context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
- VKRESULT(vkResetFences(context.device, 1, &submission_fences[virtual_frame_index]))
-
- auto* cmd_buf = command_buffers[virtual_frame_index];
- api.start_record(cmd_buf);
+void upload_image(void* data, size_t size) {
+ // copy to staging buffer
- api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, texture->device_image);
-
- api.copy_buffer(cmd_buf, staging_buffer, texture->device_image);
-
- api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, texture->device_image);
-
- api.end_record(cmd_buf);
-
-
- api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]);
-
- VKRESULT(vkWaitForFences(context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
+ // allocate command buffers
+ // get command buffer
+ // copy to gpu resident texture
}
Buffer* vkrenderer::create_buffer(size_t size) {
@@ -176,8 +131,9 @@ Buffer* vkrenderer::create_index_buffer(size_t size) {
return buffer;
}
-Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat format) {
+Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat format, Sampler *sampler) {
auto* texture = new Texture();
+ texture->sampler = sampler;
texture->device_image = api.create_image(
{ .width = (uint32_t)width, .height = (uint32_t)height, .depth = 1 },
format,
@@ -220,7 +176,7 @@ Primitive* vkrenderer::create_primitive(PrimitiveRenderpass& primitive_render_pa
void vkrenderer::render() {
begin_frame();
- auto* cmd_buf = command_buffers[virtual_frame_index];
+ auto* cmd_buf = graphics_command_buffers[virtual_frame_index];
for (auto& renderpass: renderpasses) {
renderpass->execute(*this, cmd_buf);
@@ -242,7 +198,51 @@ void vkrenderer::render() {
finish_frame();
}
+// private functions
+void vkrenderer::begin_frame() {
+
+ VKRESULT(vkWaitForFences(context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
+ VKRESULT(vkResetFences(context.device, 1, &submission_fences[virtual_frame_index]))
+
+ swapchain_image_index = 0;
+ auto acquire_result = vkAcquireNextImageKHR(context.device, swapchain.handle, UINT64_MAX, acquire_semaphores[virtual_frame_index], VK_NULL_HANDLE, &swapchain_image_index);
+ handle_swapchain_result(acquire_result);
+
+ api.start_record(graphics_command_buffers[virtual_frame_index]);
+}
+
+void vkrenderer::finish_frame() {
+ auto* cmd_buf = graphics_command_buffers[virtual_frame_index];
+
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, swapchain.images[swapchain_image_index]);
+
+ api.end_record(cmd_buf);
+
+ // wait for acquire + copy semaphores
+
+ api.submit_graphics(cmd_buf, acquire_semaphores[virtual_frame_index], execution_semaphores[virtual_frame_index], submission_fences[virtual_frame_index]);
+
+ auto present_result = api.present(swapchain, swapchain_image_index, execution_semaphores[virtual_frame_index]);
+ handle_swapchain_result(present_result);
+
+ virtual_frame_index = ++virtual_frame_index % virtual_frames_count;
+}
+
+
+void vkrenderer::handle_swapchain_result(VkResult function_result) {
+ switch(function_result) {
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ return recreate_swapchain();
+ case VK_ERROR_SURFACE_LOST_KHR:
+ assert(true && "surface lost");
+ default:
+ return;
+ }
+}
+
+
Buffer::Buffer(size_t size)
: buffer_size(size) {
device_buffer = vkrenderer::api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
}
+