aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/compute-renderpass.hpp10
-rw-r--r--include/material.hpp2
-rw-r--r--include/primitive-renderpass.hpp97
-rw-r--r--include/renderpass.hpp12
-rw-r--r--include/vk-api.hpp71
-rw-r--r--include/vk-renderer.hpp65
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/compute-renderpass.cpp14
-rw-r--r--src/gltf.cpp512
-rw-r--r--src/main.cpp249
-rw-r--r--src/primitive-renderpass.cpp150
-rw-r--r--src/scene.cpp14
-rw-r--r--src/vk-api.cpp405
-rw-r--r--src/vk-context.cpp7
-rw-r--r--src/vk-renderer.cpp315
15 files changed, 1114 insertions, 810 deletions
diff --git a/include/compute-renderpass.hpp b/include/compute-renderpass.hpp
index a581930..641d4b1 100644
--- a/include/compute-renderpass.hpp
+++ b/include/compute-renderpass.hpp
@@ -14,8 +14,12 @@ class ComputeRenderpass : public Renderpass {
: Renderpass(api)
{}
+ ~ComputeRenderpass() {
+ api.destroy_pipeline(pipeline);
+ }
- void set_pipeline(std::string& shader_name) override final;
+
+ void set_pipeline(std::string& shader_name);
void set_dispatch_size(size_t count_x, size_t count_y, size_t count_z);
@@ -26,7 +30,7 @@ class ComputeRenderpass : public Renderpass {
void set_constant(off_t offset, Buffer* buffer);
// TODO: Do not use vulkan api type
- void execute(VkCommandBuffer command_buffer) override final;
+ void execute(vkrenderer& renderer, VkCommandBuffer command_buffer) override final;
Texture* output_texture;
@@ -39,4 +43,6 @@ class ComputeRenderpass : public Renderpass {
size_t group_count_x;
size_t group_count_y;
size_t group_count_z;
+
+ pipeline pipeline;
};
diff --git a/include/material.hpp b/include/material.hpp
index 0336fb5..780e68d 100644
--- a/include/material.hpp
+++ b/include/material.hpp
@@ -13,7 +13,7 @@ struct material {
color base_color;
texture base_color_texture;
texture metallic_roughness_texture;
- float metalness = 0.f;
+ float metalness = 1.f;
float roughness = 1.f;
};
diff --git a/include/primitive-renderpass.hpp b/include/primitive-renderpass.hpp
new file mode 100644
index 0000000..45b43e9
--- /dev/null
+++ b/include/primitive-renderpass.hpp
@@ -0,0 +1,97 @@
+#pragma once
+
+#include <stdint.h>
+#include <vector>
+#include <array>
+
+#include "vk-renderer.hpp"
+#include "renderpass.hpp"
+
+class Buffer;
+class Texture;
+class Sampler;
+class Primitive;
+
+class PrimitiveRenderpass : public Renderpass {
+ public:
+
+ PrimitiveRenderpass(vkapi& api);
+
+ void add_primitive(Primitive* new_primitive);
+
+ void add_color_attachment(VkFormat format);
+
+ void set_depth_stencil(Texture* depth_stencil);
+
+ void set_viewport(float x, float y, float width, float height);
+
+ void set_color_attachment(uint32_t index, Texture* attachment);
+
+ void finalize_render_pass();
+
+ void execute(vkrenderer& renderer, VkCommandBuffer command_buffer) override final;
+
+ VkRenderPass render_pass = VK_NULL_HANDLE;
+
+ private:
+
+ void create_framebuffers();
+
+ void recreate_framebuffers();
+
+ VkViewport viewport = { .minDepth = 0.f, .maxDepth = 1.f };
+
+ std::vector<Texture*> color_attachments;
+ std::vector<VkImageView> color_attachments_view;
+ std::vector<VkFormat> color_attachments_format;
+
+ std::array<framebuffer, vkrenderer::virtual_frames_count> framebuffers;
+
+ std::vector<Primitive*> primitives;
+};
+
+
+class Primitive {
+ public:
+
+ Primitive(vkapi& api, PrimitiveRenderpass& render_pass)
+ : api(api), primitive_render_pass(render_pass)
+ {};
+
+ void set_pipeline(std::string& shader_name);
+
+ void set_constant_offset(off_t offset);
+ void set_constant(off_t offset, uint64_t* constant);
+ void set_constant(off_t offset, Texture* texture);
+ void set_constant(off_t offset, Buffer* buffer);
+ void set_constant(off_t offset, Sampler* sampler);
+
+ void set_index_buffer(Buffer* index_buffer);
+
+ void set_scissor(int32_t x, int32_t y, uint32_t width, uint32_t height);
+
+ void set_draw_info(size_t vertex_count, off_t first_vertex, off_t vertex_offset);
+
+ void render(VkCommandBuffer command_buffer);
+
+
+private:
+
+ vkapi& api;
+
+ PrimitiveRenderpass& primitive_render_pass;
+
+ pipeline pipeline;
+
+ Buffer* index_buffer;
+
+ size_t element_count;
+ off_t first_vertex;
+ off_t vertex_offset;
+
+ off_t constant_offset;
+
+ VkRect2D scissor = {};
+
+ std::array<uint8_t, 64> constants;
+};
diff --git a/include/renderpass.hpp b/include/renderpass.hpp
index 64947b6..a444c64 100644
--- a/include/renderpass.hpp
+++ b/include/renderpass.hpp
@@ -2,7 +2,7 @@
#include <string>
-#include "vk-api.hpp"
+#include "vk-renderer.hpp"
class Renderpass {
public:
@@ -11,17 +11,11 @@ class Renderpass {
:api(api)
{};
- virtual ~Renderpass() {
- api.destroy_pipeline(pipeline);
- }
-
- virtual void set_pipeline(std::string& shader_name) = 0;
+ virtual ~Renderpass() {};
// TODO: Do not use vulkan api type
- virtual void execute(VkCommandBuffer command_buffer) = 0;
+ virtual void execute(vkrenderer& renderer, VkCommandBuffer command_buffer) = 0;
protected:
vkapi &api;
-
- pipeline pipeline;
};
diff --git a/include/vk-api.hpp b/include/vk-api.hpp
index 1b9f51f..0f1431a 100644
--- a/include/vk-api.hpp
+++ b/include/vk-api.hpp
@@ -1,6 +1,7 @@
#ifndef __VK_API_HPP_
#define __VK_API_HPP_
+#include <stdint.h>
#include <vector>
#include <map>
#include <iostream>
@@ -22,6 +23,7 @@ struct pipeline {
};
using bindless_index = uint32_t;
+using handle = uint32_t;
struct image {
VkImage handle;
@@ -31,6 +33,7 @@ struct image {
VkImageSubresourceRange subresource_range;
VkFormat format;
VkExtent3D size;
+ VkImageUsageFlags usages;
bindless_index bindless_storage_index;
bindless_index bindless_sampled_index;
@@ -40,13 +43,18 @@ struct image {
};
struct swapchain {
- size_t image_count;
- std::vector<image> images;
+ uint32_t image_count;
+ std::vector<handle> images;
VkSwapchainKHR handle;
VkSurfaceFormatKHR surface_format;
VkExtent2D extent;
};
+struct framebuffer {
+ VkFramebuffer handle;
+ VkExtent2D size;
+};
+
struct sampler {
VkSampler handle;
bindless_index bindless_index;
@@ -101,16 +109,16 @@ class vkapi {
vkapi();
~vkapi();
- buffer create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, VmaMemoryUsage mem_usage);
- void copy_buffer(VkCommandBuffer cmd_buf, buffer src, buffer dst, size_t size);
- void copy_buffer(VkCommandBuffer cmd_buf, buffer src, image dst);
- void destroy_buffer(buffer& buffer);
+ handle create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, VmaMemoryUsage mem_usage);
+ void copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, size_t size);
+ void copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst);
+ void destroy_buffer(handle buffer);
- image create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages);
- void destroy_image(image &image);
- std::vector<image> create_images(VkExtent3D size, VkFormat format, VkImageUsageFlags usages, size_t image_count);
- void destroy_images(std::vector<image> &images);
+ handle create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages);
+ void destroy_image(handle image);
+ std::vector<handle> create_images(VkExtent3D size, VkFormat format, VkImageUsageFlags usages, size_t image_count);
+ void destroy_images(std::vector<handle>& images);
VkFence create_fence();
@@ -124,8 +132,8 @@ class vkapi {
std::vector<VkSemaphore> create_semaphores(size_t semaphores_count);
void destroy_semaphores(std::vector<VkSemaphore> &semaphores);
- sampler create_sampler(VkFilter filter, VkSamplerAddressMode address_mode);
- void destroy_sampler(sampler sampler);
+ handle create_sampler(VkFilter filter, VkSamplerAddressMode address_mode);
+ void destroy_sampler(handle sampler);
std::vector<VkCommandBuffer> create_command_buffers(size_t command_buffers_count);
@@ -137,10 +145,10 @@ class vkapi {
void destroy_render_pass(VkRenderPass render_pass);
- VkFramebuffer create_framebuffer(VkRenderPass render_pass, std::vector<image>& images, VkExtent2D size);
- std::vector<VkFramebuffer> create_framebuffers(VkRenderPass render_pass, std::vector<image>& images, VkExtent2D size, uint32_t framebuffer_count);
- void destroy_framebuffer(VkFramebuffer framebuffer);
- void destroy_framebuffers(std::vector<VkFramebuffer>& framebuffers);
+ framebuffer create_framebuffer(VkRenderPass render_pass, std::vector<VkFormat>& formats, VkExtent2D size);
+ std::vector<framebuffer> create_framebuffers(VkRenderPass render_pass, std::vector<VkFormat>& formats, VkExtent2D size, uint32_t framebuffer_count);
+ void destroy_framebuffer(framebuffer framebuffer);
+ void destroy_framebuffers(std::vector<framebuffer>& framebuffers);
pipeline create_compute_pipeline(const char* shader_name);
@@ -159,27 +167,27 @@ class vkapi {
swapchain create_swapchain(VkSurfaceKHR surface, size_t min_image_count, VkImageUsageFlags usages, VkSwapchainKHR old_swapchain);
void destroy_swapchain(swapchain& swapchain);
- void update_descriptor_image(image &img, VkDescriptorType type);
- void update_descriptor_images(std::vector<image> &images, VkDescriptorType type);
- void update_descriptor_sampler(sampler &sampler);
- void update_descriptor_samplers(std::vector<sampler> &samplers);
+ void update_descriptor_image(handle img, VkDescriptorType type);
+ void update_descriptor_images(std::vector<handle> &images, VkDescriptorType type);
+ void update_descriptor_sampler(handle sampler);
+ void update_descriptor_samplers(std::vector<handle> &samplers);
void update_constants(VkCommandBuffer command_buffer, VkShaderStageFlagBits shader_stage, off_t offset, size_t size, void* data);
void start_record(VkCommandBuffer command_buffer);
- void image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, image& image);
+ void image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, handle image);
- void begin_render_pass(VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D size, pipeline& pipeline);
+ void begin_render_pass(VkCommandBuffer command_buffer, VkRenderPass render_pass, std::vector<VkImageView>& attachments, framebuffer framebuffer, VkExtent2D size);
void end_render_pass(VkCommandBuffer command_buffer);
void run_compute_pipeline(VkCommandBuffer command_buffer, pipeline& pipeline, size_t group_count_x, size_t group_count_y, size_t group_count_z);
void draw(VkCommandBuffer command_buffer, pipeline& pipeline, uint32_t vertex_count, uint32_t vertex_offset);
- void draw(VkCommandBuffer command_buffer, pipeline& pipeline, buffer& index_buffer, uint32_t primitive_count, uint32_t indices_offset, uint32_t vertices_offset);
+ void draw(VkCommandBuffer command_buffer, pipeline& pipeline, handle index_buffer, uint32_t primitive_count, uint32_t indices_offset, uint32_t vertices_offset);
- void blit_full(VkCommandBuffer command_buffer, image& src_image, image& dst_image);
+ void blit_full(VkCommandBuffer command_buffer, handle src_image, handle dst_image);
void end_record(VkCommandBuffer command_buffer);
@@ -187,6 +195,10 @@ class vkapi {
VkResult present(swapchain& swapchain, uint32_t image_index, VkSemaphore wait_semaphore);
+ const buffer& get_buffer(handle buffer_handle) { return *buffers[buffer_handle]; };
+ const image& get_image(handle image_handle) { return *images[image_handle]; };
+ const sampler& get_sampler(handle sampler_handle) { return *samplers[sampler_handle]; };
+
vkcontext context;
private:
@@ -195,12 +207,13 @@ class vkapi {
const char* shader_stage_extension(VkShaderStageFlags shader_stage);
- std::map<VkBuffer, buffer> buffers;
- std::map<VkImage, image> images;
- std::map<VkSampler, sampler>samplers;
+ // TODO: Use freelists instead
+ std::vector<buffer*> buffers;
+ std::vector<image*> images;
+ std::vector<sampler*> samplers;
- VkCommandPool command_pool;
- VkDescriptorPool descriptor_pool;
+ VkCommandPool command_pool;
+ VkDescriptorPool descriptor_pool;
};
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
index 76dfffc..864bc48 100644
--- a/include/vk-renderer.hpp
+++ b/include/vk-renderer.hpp
@@ -2,14 +2,16 @@
#define __VK_RENDERER_HPP_
#include <stdint.h>
+#include <sys/types.h>
#include <vector>
#include "vk-api.hpp"
-#include "vulkan/vulkan_core.h"
class Renderpass;
class ComputeRenderpass;
+class PrimitiveRenderpass;
+class Primitive;
class window;
class Texture;
@@ -24,67 +26,67 @@ class vkrenderer {
void begin_frame();
- void ui();
-
void compute(uint32_t width, uint32_t height);
void finish_frame();
void recreate_swapchain();
- void update_image(Texture* texture, void* data, size_t size);
+ void update_image(Texture* texture, void* data);
+
+ void update_buffer(Buffer* buffer, void* data, off_t offset, size_t size);
Buffer* create_buffer(size_t size, bool isStatic);
+ Buffer* create_index_buffer(size_t size, bool isStatic);
+
Texture* create_2d_texture(size_t width, size_t height, VkFormat format);
Sampler* create_sampler(VkFilter filter, VkSamplerAddressMode address_mode);
ComputeRenderpass* create_compute_renderpass();
+ PrimitiveRenderpass* create_primitive_renderpass();
+
+ Primitive* create_primitive(PrimitiveRenderpass& primitive_render_pass);
+
void render();
uint32_t frame_index() { return this->virtual_frame_index; }
- private:
+ Texture* back_buffer() { return swapchain_textures[swapchain_image_index]; }
- vkapi api;
+ VkFormat back_buffer_format() { return swapchain.surface_format.format; }
- std::vector<Renderpass*> renderpasses;
+ static constexpr uint32_t virtual_frames_count = 2;
+ private:
void handle_swapchain_result(VkResult function_result);
- // vkapi api;
+ vkapi api;
+
+ std::vector<Renderpass*> renderpasses;
uint32_t virtual_frame_index = 0;
uint32_t swapchain_image_index = 0;
- sampler ui_texture_sampler;
- image ui_texture;
-
std::vector<VkCommandBuffer> command_buffers;
- buffer staging_buffer;
+ handle staging_buffer;
pipeline tonemapping_pipeline;
- std::vector<buffer> ui_vertex_buffers;
- std::vector<buffer> ui_index_buffers;
- pipeline ui_pipeline;
- VkRenderPass render_pass;
- std::vector<VkFramebuffer> framebuffers;
-
std::vector<VkFence> submission_fences;
std::vector<VkSemaphore> execution_semaphores;
std::vector<VkSemaphore> acquire_semaphores;
VkSurfaceKHR platform_surface;
swapchain swapchain;
+ std::vector<Texture*> swapchain_textures;
const uint32_t min_swapchain_image_count = 3;
- static constexpr uint32_t virtual_frames_count = 2;
};
// TODO: Move those to there own files
@@ -93,39 +95,26 @@ class Texture {
sampler sampler;
- image device_image;
+ handle device_image;
};
class Sampler {
public:
- sampler device_sampler;
+
+ handle device_sampler;
};
class Buffer {
public:
Buffer(vkrenderer* renderer, size_t size, bool isStatic)
- : renderer(renderer), size(size), isStatic(isStatic) {}
-
- void* ptr() {
- size_t offset = isStatic ? 0 : size * renderer->frame_index();
- return (uint8_t*)device_buffer.alloc_info.pMappedData + offset;
- }
+ : size(size), isStatic(isStatic) {}
- unsigned long long device_address() {
- size_t offset = isStatic ? 0 : size * renderer->frame_index();
- return device_buffer.device_address + offset;
- }
-
- buffer device_buffer;
-
- private:
-
- bool isStatic;
+ handle device_buffer;
size_t size;
- vkrenderer* renderer;
+ bool isStatic;
};
#endif // !__VK_RENDERER_HPP_
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2956cb6..ff5f034 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,6 +24,7 @@ add_executable(
scene.cpp
gltf.cpp
compute-renderpass.cpp
+ primitive-renderpass.cpp
)
if(UNIX AND NOT APPLE)
diff --git a/src/compute-renderpass.cpp b/src/compute-renderpass.cpp
index c680bac..7399ae3 100644
--- a/src/compute-renderpass.cpp
+++ b/src/compute-renderpass.cpp
@@ -11,8 +11,10 @@ void ComputeRenderpass::set_pipeline(std::string& shader_name) {
void ComputeRenderpass::set_ouput_texture(Texture* output_texture) {
this->output_texture = output_texture;
+ auto image = api.get_image(output_texture->device_image);
+
// TODO: Remove hardcoded offset
- memcpy(constants.data() + 56, &output_texture->device_image.bindless_storage_index, sizeof(bindless_index));
+ memcpy(constants.data() + 56, &image.bindless_storage_index, sizeof(bindless_index));
}
void ComputeRenderpass::set_dispatch_size(size_t count_x, size_t count_y, size_t count_z) {
@@ -26,17 +28,19 @@ void ComputeRenderpass::set_constant(off_t offset, uint64_t* constant) {
}
void ComputeRenderpass::set_constant(off_t offset, Texture* texture) {
- memcpy(constants.data() + offset, (void*)&texture->device_image.bindless_storage_index, sizeof(bindless_index));
+ auto image = api.get_image(texture->device_image);
+
+ memcpy(constants.data() + offset, (void*)&image.bindless_storage_index, sizeof(bindless_index));
input_textures.push_back(texture);
}
void ComputeRenderpass::set_constant(off_t offset, Buffer* buffer) {
- auto address = buffer->device_address();
- memcpy(constants.data() + offset, (void*)&address, sizeof(VkDeviceAddress));
+ auto device_buffer = api.get_buffer(buffer->device_buffer);
+ memcpy(constants.data() + offset, (void*)&device_buffer.device_address, sizeof(VkDeviceAddress));
}
-void ComputeRenderpass::execute(VkCommandBuffer command_buffer) {
+void ComputeRenderpass::execute(vkrenderer& renderer, VkCommandBuffer command_buffer) {
api.update_constants(command_buffer, VK_SHADER_STAGE_COMPUTE_BIT, 0, 64, (void*)&constants);
for (auto& texture: input_textures) {
diff --git a/src/gltf.cpp b/src/gltf.cpp
index b05e71e..2f37a3c 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -1,256 +1,256 @@
-#include "gltf.hpp"
-
-#include <fstream>
-#include <cstring>
-
-#define STB_IMAGE_IMPLEMENTATION
-#include "thirdparty/stb_image.h"
-
-#include "utils.hpp"
-
-node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) {
- std::fstream f(path / filename);
- json gltf_json;
-
- f >> gltf_json;
-
- auto &scene = gltf_json["scenes"][0];
-
- auto &buffers = gltf_json["buffers"];
- auto buffer_index = 0;
- auto buffers_content = std::vector<std::vector<uint8_t>>(buffers.size());
- for (auto &buffer: buffers) {
- auto buffer_path = (path / buffer["uri"].get<std::string>()).string();
- buffers_content[buffer_index] = read_file(buffer_path);
- buffer_index++;
- }
-
- auto textures = load_textures(gltf_json, path, renderer);
- auto materials = load_materials(gltf_json, textures);
-
- auto meshes = load_meshes(gltf_json, buffers_content, materials);
-
- node root_node;
- auto &root_children = scene["nodes"];
- uint32_t root_children_count = scene["nodes"].size();
- root_node.children.resize(root_children_count);
-
- for (size_t child_index = 0; child_index < root_children_count; child_index++) {
- load_node(gltf_json, root_children[child_index].get<uint32_t>(), root_node.children[child_index], meshes);
- }
-
- return std::move(root_node);
-}
-
-void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector<mesh> &meshes) {
- auto &gltf_node = gltf_json["nodes"][index];
-
- if (gltf_node.contains("children")) {
- auto &children = gltf_node["children"];
- uint32_t children_count = gltf_node["children"];
- parent.children.resize(children_count);
-
- for (size_t child_index = 0; child_index < children_count; child_index++) {
- load_node(gltf_json, children[child_index].get<uint32_t>(), parent.children[child_index], meshes);
- }
- }
-
- if (gltf_node.contains("mesh")) {
- parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get<uint32_t>()]);
- }
-}
-
-std::vector<mesh> gltf::load_meshes(json &gltf_json, std::vector<std::vector<uint8_t>> &buffers_content, std::vector<material> &materials) {
- auto &gltf_meshes = gltf_json["meshes"];
- auto meshes_count = gltf_meshes.size();
- std::vector<mesh> meshes { meshes_count };
-
- for(size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) {
- auto &gltf_mesh = gltf_meshes[mesh_index];
- auto &primitives = gltf_mesh["primitives"];
- auto &mesh = meshes[mesh_index];
-
- for (auto& primitive: primitives) {
- auto &&part = load_primitive(gltf_json, primitive, buffers_content, materials);
- mesh.vertices_count += part.vertices_count;
- mesh.triangles_count += part.triangles_count;
- mesh.parts.emplace_back(std::move(part));
- }
- }
-
- return std::move(meshes);
-}
-
-std::vector<texture> gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) {
- auto &gltf_images = gltf_json["images"];
- auto images_count = gltf_images.size();
- std::vector<Texture*> images { images_count };
-
- for (size_t image_index = 0; image_index < images_count; image_index++) {
- auto &gltf_image = gltf_images[image_index];
- int x,y,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 = renderer.create_2d_texture(static_cast<uint32_t>(x), static_cast<uint32_t>(y), VK_FORMAT_R8G8B8A8_UNORM);
-
- renderer.update_image(img, data, x * y * 4);
-
- stbi_image_free(data);
-
- images[image_index] = std::move(img);
- }
-
- auto &gltf_samplers = gltf_json["samplers"];
- auto samplers_count = gltf_samplers.size();
- std::vector<Sampler*> samplers { samplers_count };
-
- for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- samplers[sampler_index] = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- }
-
- auto &gltf_textures = gltf_json["textures"];
- auto textures_count = gltf_textures.size();
- std::vector<texture> textures { textures_count };
-
- 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 sampler_id = 0;
- if (gltf_texture.contains("sampler")) {
- auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
- auto &sampler = samplers[sampler_index];
- sampler_id = sampler->device_sampler.bindless_index;
- }
-
- textures[texture_index] = texture {
- .image_id = image->device_image.bindless_sampled_index,
- .sampler_id = sampler_id
- };
- }
-
- return std::move(textures);
-}
-
-std::vector<material> gltf::load_materials(json &gltf_json, std::vector<texture> &textures) {
- auto &gltf_materials = gltf_json["materials"];
- auto materials_count = gltf_materials.size();
- std::vector<material> materials { materials_count };
-
- for(size_t material_index = 0; material_index < materials_count; material_index++) {
- auto& gltf_material = gltf_materials[material_index];
- auto& material = materials[material_index];
-
- if (gltf_material.contains("pbrMetallicRoughness")) {
- auto &pbr_params = gltf_material["pbrMetallicRoughness"];
-
- if (pbr_params.contains("baseColorFactor")) {
- auto &base_color = pbr_params["baseColorFactor"];
- material.base_color.v[0] = base_color[0].get<float>();
- material.base_color.v[1] = base_color[1].get<float>();
- material.base_color.v[2] = base_color[2].get<float>();
- material.base_color.v[3] = base_color[3].get<float>();
- } else
- material.base_color = vec3(1.f);
-
- if (pbr_params.contains("baseColorTexture")) {
- auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
- material.base_color_texture = textures[base_color_index];
- }
-
- if (pbr_params.contains("metallicFactor"))
- material.metalness = pbr_params["metallicFactor"].get<float>();
- else
- material.metalness = 1.0;
-
- if (pbr_params.contains("roughnessFactor"))
- material.roughness = pbr_params["roughnessFactor"].get<float>();
- else
- material.roughness = 1.0;
-
- if (pbr_params.contains("metallicRoughnessTexture")) {
- auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
- material.metallic_roughness_texture = textures[metallic_roughness_index];
- }
- }
- }
-
- return std::move(materials);
-}
-
-mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content, std::vector<material> &materials) {
- auto part = mesh_part();
- auto &accessors = gltf_json["accessors"];
-
- {
- auto indices_accessor_index = primitive["indices"].get<uint32_t>();
- auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get<uint32_t>();
- auto &indices_view = gltf_json["bufferViews"][indices_view_index];
-
- auto indices_buffer_index = indices_view["buffer"].get<uint32_t>();
- auto indices_offset = indices_view["byteOffset"].get<size_t>();
- auto indices_length = indices_view["byteLength"].get<size_t>();
-
- auto &indices_buffer = buffers_content[indices_buffer_index];
- uint16_t* indices_start = (uint16_t*)(indices_buffer.data() + indices_offset);
-
- part.indices.resize(indices_length / sizeof(uint16_t));
- std::memcpy(part.indices.data(), indices_start, indices_length);
- }
-
- {
- auto positions_accessor_index = primitive["attributes"]["POSITION"].get<uint32_t>();
- auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get<uint32_t>();
- auto &positions_view = gltf_json["bufferViews"][positions_view_index];
-
- auto positions_buffer_index = positions_view["buffer"].get<uint32_t>();
- auto positions_offset = positions_view["byteOffset"].get<size_t>();
- auto positions_length = positions_view["byteLength"].get<size_t>();
-
- auto &positions_buffer = buffers_content[positions_buffer_index];
- float* positions_start = (float*)(positions_buffer.data() + positions_offset);
-
- part.positions.resize(positions_length / sizeof(float));
- std::memcpy(part.positions.data(), positions_start, positions_length);
- }
-
- {
- auto normals_accessor_index = primitive["attributes"]["NORMAL"].get<uint32_t>();
- auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get<uint32_t>();
- auto &normals_view = gltf_json["bufferViews"][normals_view_index];
-
- auto normals_buffer_index = normals_view["buffer"].get<uint32_t>();
- auto normals_offset = normals_view["byteOffset"].get<size_t>();
- auto normals_length = normals_view["byteLength"].get<size_t>();
-
- auto &normals_buffer = buffers_content[normals_buffer_index];
- float* normals_start = (float*)(normals_buffer.data() + normals_offset);
-
- part.normals.resize(normals_length / sizeof(float));
- std::memcpy(part.normals.data(), normals_start, normals_length);
- }
-
- {
- auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get<uint32_t>();
- auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get<uint32_t>();
- auto &uvs_view = gltf_json["bufferViews"][uvs_view_index];
-
- auto uvs_buffer_index = uvs_view["buffer"].get<uint32_t>();
- auto uvs_offset = uvs_view["byteOffset"].get<size_t>();
- auto uvs_length = uvs_view["byteLength"].get<size_t>();
-
- auto &uvs_buffer = buffers_content[uvs_buffer_index];
- float* uvs_start = (float*)(uvs_buffer.data() + uvs_offset);
-
- part.uvs.resize(uvs_length / sizeof(float));
- std::memcpy(part.uvs.data(), uvs_start, uvs_length);
- }
-
- part.mat = materials[primitive["material"].get<uint32_t>()];
- part.vertices_count = part.positions.size() / 3;
- part.triangles_count = part.indices.size() / 3;
-
- return std::move(part);
-}
+#include "gltf.hpp"
+
+#include <fstream>
+#include <cstring>
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "thirdparty/stb_image.h"
+
+#include "utils.hpp"
+
+node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) {
+ std::fstream f(path / filename);
+ json gltf_json;
+
+ f >> gltf_json;
+
+ auto &scene = gltf_json["scenes"][0];
+
+ auto &buffers = gltf_json["buffers"];
+ auto buffer_index = 0;
+ auto buffers_content = std::vector<std::vector<uint8_t>>(buffers.size());
+ for (auto &buffer: buffers) {
+ auto buffer_path = (path / buffer["uri"].get<std::string>()).string();
+ buffers_content[buffer_index] = read_file(buffer_path);
+ buffer_index++;
+ }
+
+ auto textures = load_textures(gltf_json, path, renderer);
+ auto materials = load_materials(gltf_json, textures);
+
+ auto meshes = load_meshes(gltf_json, buffers_content, materials);
+
+ node root_node;
+ auto &root_children = scene["nodes"];
+ uint32_t root_children_count = scene["nodes"].size();
+ root_node.children.resize(root_children_count);
+
+ for (size_t child_index = 0; child_index < root_children_count; child_index++) {
+ load_node(gltf_json, root_children[child_index].get<uint32_t>(), root_node.children[child_index], meshes);
+ }
+
+ return std::move(root_node);
+}
+
+void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector<mesh> &meshes) {
+ auto &gltf_node = gltf_json["nodes"][index];
+
+ if (gltf_node.contains("children")) {
+ auto &children = gltf_node["children"];
+ uint32_t children_count = gltf_node["children"];
+ parent.children.resize(children_count);
+
+ for (size_t child_index = 0; child_index < children_count; child_index++) {
+ load_node(gltf_json, children[child_index].get<uint32_t>(), parent.children[child_index], meshes);
+ }
+ }
+
+ if (gltf_node.contains("mesh")) {
+ parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get<uint32_t>()]);
+ }
+}
+
+std::vector<mesh> gltf::load_meshes(json &gltf_json, std::vector<std::vector<uint8_t>> &buffers_content, std::vector<material> &materials) {
+ auto &gltf_meshes = gltf_json["meshes"];
+ auto meshes_count = gltf_meshes.size();
+ std::vector<mesh> meshes { meshes_count };
+
+ for(size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) {
+ auto &gltf_mesh = gltf_meshes[mesh_index];
+ auto &primitives = gltf_mesh["primitives"];
+ auto &mesh = meshes[mesh_index];
+
+ for (auto& primitive: primitives) {
+ auto &&part = load_primitive(gltf_json, primitive, buffers_content, materials);
+ mesh.vertices_count += part.vertices_count;
+ mesh.triangles_count += part.triangles_count;
+ mesh.parts.emplace_back(std::move(part));
+ }
+ }
+
+ return std::move(meshes);
+}
+
+std::vector<texture> gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) {
+ auto &gltf_images = gltf_json["images"];
+ auto images_count = gltf_images.size();
+ std::vector<Texture*> images { images_count };
+
+ for (size_t image_index = 0; image_index < images_count; image_index++) {
+ auto &gltf_image = gltf_images[image_index];
+ int x,y,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 = renderer.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] = std::move(img);
+ }
+
+ auto &gltf_samplers = gltf_json["samplers"];
+ auto samplers_count = gltf_samplers.size();
+ std::vector<Sampler*> samplers { samplers_count };
+
+ for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
+ samplers[sampler_index] = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ }
+
+ auto &gltf_textures = gltf_json["textures"];
+ auto textures_count = gltf_textures.size();
+ std::vector<texture> textures { textures_count };
+
+ 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 sampler_id = 0;
+ // if (gltf_texture.contains("sampler")) {
+ // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
+ // auto &sampler = samplers[sampler_index];
+ // sampler_id = sampler->device_sampler.bindless_index;
+ // }
+
+ // textures[texture_index] = texture {
+ // .image_id = image->device_image.bindless_sampled_index,
+ // .sampler_id = sampler_id
+ // };
+ }
+
+ return std::move(textures);
+}
+
+std::vector<material> gltf::load_materials(json &gltf_json, std::vector<texture> &textures) {
+ auto &gltf_materials = gltf_json["materials"];
+ auto materials_count = gltf_materials.size();
+ std::vector<material> materials { materials_count };
+
+ for(size_t material_index = 0; material_index < materials_count; material_index++) {
+ auto& gltf_material = gltf_materials[material_index];
+ auto& material = materials[material_index];
+
+ if (gltf_material.contains("pbrMetallicRoughness")) {
+ auto &pbr_params = gltf_material["pbrMetallicRoughness"];
+
+ if (pbr_params.contains("baseColorFactor")) {
+ auto &base_color = pbr_params["baseColorFactor"];
+ material.base_color.v[0] = base_color[0].get<float>();
+ material.base_color.v[1] = base_color[1].get<float>();
+ material.base_color.v[2] = base_color[2].get<float>();
+ material.base_color.v[3] = base_color[3].get<float>();
+ } else
+ material.base_color = vec3(1.f);
+
+ if (pbr_params.contains("baseColorTexture")) {
+ auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
+ material.base_color_texture = textures[base_color_index];
+ }
+
+ if (pbr_params.contains("metallicFactor"))
+ material.metalness = pbr_params["metallicFactor"].get<float>();
+ else
+ material.metalness = 1.0;
+
+ if (pbr_params.contains("roughnessFactor"))
+ material.roughness = pbr_params["roughnessFactor"].get<float>();
+ else
+ material.roughness = 1.0;
+
+ if (pbr_params.contains("metallicRoughnessTexture")) {
+ auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
+ material.metallic_roughness_texture = textures[metallic_roughness_index];
+ }
+ }
+ }
+
+ return std::move(materials);
+}
+
+mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content, std::vector<material> &materials) {
+ auto part = mesh_part();
+ auto &accessors = gltf_json["accessors"];
+
+ {
+ auto indices_accessor_index = primitive["indices"].get<uint32_t>();
+ auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get<uint32_t>();
+ auto &indices_view = gltf_json["bufferViews"][indices_view_index];
+
+ auto indices_buffer_index = indices_view["buffer"].get<uint32_t>();
+ auto indices_offset = indices_view["byteOffset"].get<size_t>();
+ auto indices_length = indices_view["byteLength"].get<size_t>();
+
+ auto &indices_buffer = buffers_content[indices_buffer_index];
+ uint16_t* indices_start = (uint16_t*)(indices_buffer.data() + indices_offset);
+
+ part.indices.resize(indices_length / sizeof(uint16_t));
+ std::memcpy(part.indices.data(), indices_start, indices_length);
+ }
+
+ {
+ auto positions_accessor_index = primitive["attributes"]["POSITION"].get<uint32_t>();
+ auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get<uint32_t>();
+ auto &positions_view = gltf_json["bufferViews"][positions_view_index];
+
+ auto positions_buffer_index = positions_view["buffer"].get<uint32_t>();
+ auto positions_offset = positions_view["byteOffset"].get<size_t>();
+ auto positions_length = positions_view["byteLength"].get<size_t>();
+
+ auto &positions_buffer = buffers_content[positions_buffer_index];
+ float* positions_start = (float*)(positions_buffer.data() + positions_offset);
+
+ part.positions.resize(positions_length / sizeof(float));
+ std::memcpy(part.positions.data(), positions_start, positions_length);
+ }
+
+ {
+ auto normals_accessor_index = primitive["attributes"]["NORMAL"].get<uint32_t>();
+ auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get<uint32_t>();
+ auto &normals_view = gltf_json["bufferViews"][normals_view_index];
+
+ auto normals_buffer_index = normals_view["buffer"].get<uint32_t>();
+ auto normals_offset = normals_view["byteOffset"].get<size_t>();
+ auto normals_length = normals_view["byteLength"].get<size_t>();
+
+ auto &normals_buffer = buffers_content[normals_buffer_index];
+ float* normals_start = (float*)(normals_buffer.data() + normals_offset);
+
+ part.normals.resize(normals_length / sizeof(float));
+ std::memcpy(part.normals.data(), normals_start, normals_length);
+ }
+
+ {
+ auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get<uint32_t>();
+ auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get<uint32_t>();
+ auto &uvs_view = gltf_json["bufferViews"][uvs_view_index];
+
+ auto uvs_buffer_index = uvs_view["buffer"].get<uint32_t>();
+ auto uvs_offset = uvs_view["byteOffset"].get<size_t>();
+ auto uvs_length = uvs_view["byteLength"].get<size_t>();
+
+ auto &uvs_buffer = buffers_content[uvs_buffer_index];
+ float* uvs_start = (float*)(uvs_buffer.data() + uvs_offset);
+
+ part.uvs.resize(uvs_length / sizeof(float));
+ std::memcpy(part.uvs.data(), uvs_start, uvs_length);
+ }
+
+ part.mat = materials[primitive["material"].get<uint32_t>()];
+ part.vertices_count = part.positions.size() / 3;
+ part.triangles_count = part.indices.size() / 3;
+
+ return std::move(part);
+}
diff --git a/src/main.cpp b/src/main.cpp
index 45e30a3..6dbfc50 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,45 +1,54 @@
-#include <iostream>
+#include <cassert>
#include <chrono>
-#include <cstring>
#include <cstdio>
-#include <cassert>
+#include <cstring>
+#include <iostream>
-#include "thirdparty/renderdoc.h"
#include "imgui.h"
+#include "thirdparty/renderdoc.h"
#include "compute-renderpass.hpp"
+#include "primitive-renderpass.hpp"
+#include "defines.hpp"
+#include "scene.hpp"
#include "vk-renderer.hpp"
#include "window.hpp"
-#include "scene.hpp"
-#include "defines.hpp"
#if defined(LINUX)
-#include <unistd.h>
#include <dlfcn.h>
+#include <unistd.h>
#elif defined(WINDOWS)
#include <Windows.h>
#endif
+struct VkVertex {
+ float x, y;
+ float u, v;
+ uint32_t color;
+ uint32_t padding[3];
+};
+
int main() {
RENDERDOC_API_1_1_2 *rdoc_api = NULL;
#ifdef WINDOWS
// At init, on windows
- if(HMODULE mod = GetModuleHandleA("renderdoc.dll"))
- {
- pRENDERDOC_GetAPI RENDERDOC_GetAPI =
- (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
- int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void **)&rdoc_api);
- assert(ret == 1);
+ if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) {
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI =
+ (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
+ int ret =
+ RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void **)&rdoc_api);
+ assert(ret == 1);
}
#elif defined(LINUX)
// At init, on linux/android.
// For android replace librenderdoc.so with libVkLayer_GLES_RenderDoc.so
- if(void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD))
- {
- pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI");
- int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void **)&rdoc_api);
- assert(ret == 1);
+ if (void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD)) {
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI =
+ (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI");
+ int ret =
+ RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void **)&rdoc_api);
+ assert(ret == 1);
}
#endif
@@ -48,21 +57,24 @@ int main() {
uint32_t width = 400;
uint32_t height = width / aspect_ratio;
- window wnd { width , height };
+ window wnd{width, height};
float delta_time = 0.f;
uint64_t frame_count = 0;
auto start = std::chrono::high_resolution_clock::now();
auto end = std::chrono::high_resolution_clock::now();
- point3 position = { 13.0, 2.0, -3.0 };
- point3 target = { 0.0, 0.0, 0.0 };
+ point3 position = {13.0, 2.0, -3.0};
+ point3 target = {0.0, 0.0, 0.0};
auto v_fov = 90;
auto aperture = 0.1;
auto focus_distance = 10;
auto cam = camera(position, target, v_fov, (float)width / (float)height, aperture, focus_distance);
- vkrenderer renderer { wnd };
+ vkrenderer renderer{wnd};
+
+ ImGui::CreateContext();
+ auto& io = ImGui::GetIO();
auto main_scene = scene(cam, width, height, renderer);
@@ -70,8 +82,8 @@ int main() {
auto raytracing_pass = renderer.create_compute_renderpass();
raytracing_pass->set_pipeline(raytracing_shader_name);
- auto* accumulation_texture = renderer.create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
- auto* output_texture = renderer.create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
+ auto *accumulation_texture = renderer.create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
+ auto *output_texture = renderer.create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
raytracing_pass->set_constant(8, main_scene.bvh_buffer);
raytracing_pass->set_constant(16, main_scene.indices_buffer);
raytracing_pass->set_constant(24, main_scene.positions_buffer);
@@ -79,27 +91,43 @@ int main() {
raytracing_pass->set_constant(40, main_scene.uvs_buffer);
raytracing_pass->set_constant(48, main_scene.materials_buffer);
+ uint8_t *pixels = nullptr;
+ int atlas_width, atlas_height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height);
+ auto *ui_texture = renderer.create_2d_texture(atlas_width, atlas_height, VK_FORMAT_R8G8B8A8_UNORM);
+ io.Fonts->SetTexID((void *)&ui_texture);
+
+ renderer.update_image(ui_texture, pixels);
+ auto ui_texture_sampler = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+
+ Buffer* ui_vertex_buffer = nullptr;
+ Buffer* ui_index_buffer = nullptr;
+
+ std::string ui_shader_name = "ui";
+ std::vector<Primitive*> ui_primitives;
+ auto ui_pass = renderer.create_primitive_renderpass();
+ ui_pass->set_viewport(0.f, 0.f, (float)width, (float)height);
+ ui_pass->add_color_attachment(renderer.back_buffer_format());
+ ui_pass->finalize_render_pass();
auto can_render = true;
- ImGuiIO& io = ImGui::GetIO();
io.DisplaySize.x = (float)width;
io.DisplaySize.y = (float)height;
- while(wnd.isOpen) {
+ while (wnd.isOpen) {
end = std::chrono::high_resolution_clock::now();
delta_time = std::chrono::duration<float, std::milli>(end - start).count();
start = std::chrono::high_resolution_clock::now();
- ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = delta_time;
wnd.poll_events();
- for (auto event: wnd.events) {
- switch(event.type) {
+ for (auto event : wnd.events) {
+ switch (event.type) {
case EVENT_TYPES::RESIZE: {
width = event.width;
height = event.height;
@@ -133,7 +161,7 @@ int main() {
move_speed *= 10.f;
}
- vec3 move_vec {};
+ vec3 move_vec{};
switch (event.key) {
case KEYS::W: {
@@ -201,10 +229,7 @@ int main() {
break;
}
case EVENT_TYPES::MOUSE_MOVE: {
- io.MousePos = ImVec2 {
- (float)event.x,
- (float)event.y
- };
+ io.MousePos = ImVec2{(float)event.x, (float)event.y};
break;
}
default:
@@ -215,51 +240,150 @@ int main() {
wnd.events.clear();
// GUI
- ImGui::NewFrame();
+ if (can_render) {
+ ImGui::NewFrame();
- ImGui::SetNextWindowPos({ 0.f, 0.f });
- ImGui::SetNextWindowSize({ 0.f, 0.f });
- ImGui::Begin("Debug", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar);
+ // ImGui::SetNextWindowPos({0.f, 0.f});
+ // ImGui::SetNextWindowSize({0.f, 0.f});
+ // ImGui::Begin("Debug", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar);
- ImGui::Text("frame per second %u\n", static_cast<uint32_t>(1000.f / delta_time));
- ImGui::Text("frame time %f ms\n", delta_time);
- ImGui::Text("frame count %u\n", main_scene.meta.sample_index);
+ // ImGui::Text("frame per second %u\n", static_cast<uint32_t>(1000.f / delta_time));
+ // ImGui::Text("frame time %f ms\n", delta_time);
+ // ImGui::Text("frame count %u\n", main_scene.meta.sample_index);
- if (ImGui::Checkbox("depth of field", (bool*)&main_scene.meta.enable_dof)) {
- main_scene.meta.sample_index = 1;
- }
+ // if (ImGui::Checkbox("depth of field", (bool*)&main_scene.meta.enable_dof)) {
+ // main_scene.meta.sample_index = 1;
+ // }
- ImGui::SliderInt("max bounces", (int32_t*)&main_scene.meta.max_bounce, 1, 250);
- ImGui::SliderInt("min bounces", (int32_t*)&main_scene.meta.min_bounce, 1, main_scene.meta.max_bounce);
- if (ImGui::SliderInt("downscale factor", (int32_t*)&main_scene.meta.downscale_factor, 1, 32)) {
- main_scene.meta.sample_index = 1;
- }
+ // ImGui::SliderInt("max bounces", (int32_t *)&main_scene.meta.max_bounce, 1, 250);
+ // ImGui::SliderInt("min bounces", (int32_t *)&main_scene.meta.min_bounce, 1, main_scene.meta.max_bounce);
+ // if (ImGui::SliderInt("downscale factor", (int32_t *)&main_scene.meta.downscale_factor, 1, 32)) {
+ // main_scene.meta.sample_index = 1;
+ // }
- if (ImGui::Checkbox("debug bvh", (bool*)&main_scene.meta.debug_bvh)) {
- main_scene.meta.sample_index = 1;
- }
+ // if (ImGui::Checkbox("debug bvh", (bool *)&main_scene.meta.debug_bvh)) {
+ // main_scene.meta.sample_index = 1;
+ // }
- ImGui::End();
+ // ImGui::End();
+ bool open = true;
+ ImGui:ImGui::ShowDemoWindow(&open);
- ImGui::EndFrame();
+ ImGui::EndFrame();
- // To start a frame capture, call StartFrameCapture.
- // You can specify NULL, NULL for the device to capture on if you have only one device and
- // either no windows at all or only one window, and it will capture from that device.
- // See the documentation below for a longer explanation
- // if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL);
+ ImGui::Render();
- // renderer.ui();
+ // To start a frame capture, call StartFrameCapture.
+ // You can specify NULL, NULL for the device to capture on if you have only
+ // one device and either no windows at all or only one window, and it will
+ // capture from that device. See the documentation below for a longer
+ // explanation if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL);
- if (can_render) {
- std::memcpy(main_scene.scene_buffer->ptr(), &main_scene.meta, sizeof(main_scene.meta));
+ renderer.update_buffer(main_scene.scene_buffer, &main_scene.meta, 0, sizeof(main_scene.meta));
raytracing_pass->set_ouput_texture(output_texture);
raytracing_pass->set_constant(0, main_scene.scene_buffer);
raytracing_pass->set_constant(60, accumulation_texture);
+ ImDrawData* draw_data = ImGui::GetDrawData();
+
+ ui_pass->set_viewport(0.f, 0.f, (float)draw_data->DisplaySize.x, (float)draw_data->DisplaySize.y);
+
+ auto previous_size = ui_primitives.size();
+ auto commands_count = 0;
+
+ for (uint32_t draw_list_index = 0; draw_list_index < draw_data->CmdListsCount; draw_list_index++) {
+ commands_count += draw_data->CmdLists[draw_list_index]->CmdBuffer.size();
+ }
+
+ if (ui_primitives.size() < commands_count) {
+ ui_primitives.resize(commands_count);
+
+ for (size_t index = previous_size; index < ui_primitives.size(); index++) {
+ ui_primitives[index] = renderer.create_primitive(*ui_pass);
+ ui_primitives[index]->set_pipeline(ui_shader_name);
+ ui_primitives[index]->set_constant_offset(64);
+ ui_primitives[index]->set_constant(32, ui_texture);
+ ui_primitives[index]->set_constant(36, ui_texture_sampler);
+ }
+ }
+
+ float scale[] {
+ 2.f / draw_data->DisplaySize.x,
+ 2.f / draw_data->DisplaySize.y,
+ };
+ float translate[] {
+ -1.f - draw_data->DisplayPos.x * (2.f / draw_data->DisplaySize.x),
+ -1.f - draw_data->DisplayPos.y * (2.f / draw_data->DisplaySize.y),
+ };
+
+ if (!ui_vertex_buffer || ui_vertex_buffer->size < draw_data->TotalVtxCount * sizeof(VkVertex)) {
+ ui_vertex_buffer = renderer.create_buffer(draw_data->TotalVtxCount * sizeof(VkVertex), false);
+
+ for (auto& primitive : ui_primitives) {
+ primitive->set_constant(0, ui_vertex_buffer);
+ }
+ }
+
+ if (!ui_index_buffer || ui_index_buffer->size < draw_data->TotalIdxCount * sizeof(ImDrawIdx)) {
+ ui_index_buffer = renderer.create_index_buffer(draw_data->TotalIdxCount * sizeof(ImDrawIdx), false);
+
+ for (auto& primitive : ui_primitives) {
+ primitive->set_index_buffer(ui_index_buffer);
+ }
+ }
+
+ off_t vertex_buffer_offset = 0;
+ off_t index_buffer_offset = 0;
+ std::vector<VkVertex> vertices;
+ uint32_t draw_call_index = 0;
+ for (uint32_t draw_list_index = 0; draw_list_index < draw_data->CmdListsCount; draw_list_index++) {
+ auto& vertex_buffer = draw_data->CmdLists[draw_list_index]->VtxBuffer;
+ auto& index_buffer = draw_data->CmdLists[draw_list_index]->IdxBuffer;
+ vertices.resize(vertex_buffer.size());
+
+ for (size_t vert_index = 0; vert_index < vertex_buffer.Size; vert_index++) {
+ vertices[vert_index] = *((VkVertex*)&vertex_buffer[vert_index]);
+ }
+
+ renderer.update_buffer(ui_vertex_buffer, vertices.data(), vertex_buffer_offset * sizeof(VkVertex), vertices.size() * sizeof(VkVertex));
+ renderer.update_buffer(ui_index_buffer, index_buffer.Data, index_buffer_offset * sizeof(ImDrawIdx), index_buffer.size() * sizeof(ImDrawIdx));
+
+ ImDrawList* draw_list = draw_data->CmdLists[draw_list_index];
+ for (auto& draw_cmd: draw_list->CmdBuffer) {
+ auto& current_primitive = ui_primitives[draw_call_index];
+ current_primitive->set_constant(8, (uint64_t*)&scale);
+ current_primitive->set_constant(16, (uint64_t*)&translate);
+
+ ImVec2 pos = draw_data->DisplayPos;
+ current_primitive->set_scissor(
+ (int32_t)draw_cmd.ClipRect.x - pos.x,
+ (int32_t)draw_cmd.ClipRect.y - pos.y,
+ (uint32_t)draw_cmd.ClipRect.z - pos.x,
+ (uint32_t)draw_cmd.ClipRect.w - pos.y
+ );
+
+ current_primitive->set_draw_info(
+ draw_cmd.ElemCount,
+ index_buffer_offset + draw_cmd.IdxOffset,
+ vertex_buffer_offset + draw_cmd.VtxOffset
+ );
+
+ ui_pass->add_primitive(current_primitive);
+ draw_call_index++;
+ }
+
+ vertex_buffer_offset += vertex_buffer.Size;
+ index_buffer_offset += index_buffer.Size;
+ }
+
+ renderer.begin_frame();
+
+ ui_pass->set_color_attachment(0, renderer.back_buffer());
+
renderer.render();
+ renderer.finish_frame();
main_scene.meta.sample_index++;
@@ -282,7 +406,6 @@ int main() {
// write_color(std::cout, output_image[index]);
// }
-
std::cerr << "Done !" << std::endl;
return 0;
diff --git a/src/primitive-renderpass.cpp b/src/primitive-renderpass.cpp
new file mode 100644
index 0000000..f8521e3
--- /dev/null
+++ b/src/primitive-renderpass.cpp
@@ -0,0 +1,150 @@
+#include "primitive-renderpass.hpp"
+
+#include "vk-renderer.hpp"
+#include "vulkan/vulkan_core.h"
+#include <stdint.h>
+
+
+void Primitive::set_pipeline(std::string &shader_name) {
+ std::vector<VkDynamicState> dynamic_states {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR
+ };
+
+ pipeline = api.create_graphics_pipeline(shader_name.c_str(), (VkShaderStageFlagBits)(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), primitive_render_pass.render_pass, dynamic_states);
+}
+
+void Primitive::set_constant_offset(off_t offset) {
+ constant_offset = offset;
+}
+
+void Primitive::set_constant(off_t offset, uint64_t* constant) {
+ memcpy(constants.data() + offset, constant, sizeof(uint64_t));
+}
+
+void Primitive::set_constant(off_t offset, Texture* texture) {
+ auto image = api.get_image(texture->device_image);
+
+ memcpy(constants.data() + offset, (void*)&image.bindless_storage_index, sizeof(bindless_index));
+}
+
+void Primitive::set_constant(off_t offset, Buffer* buffer) {
+ auto device_buffer = api.get_buffer(buffer->device_buffer);
+ memcpy(constants.data() + offset, (void*)&device_buffer.device_address, sizeof(VkDeviceAddress));
+}
+
+void Primitive::set_constant(off_t offset, Sampler* sampler) {
+ auto device_sampler = api.get_sampler(sampler->device_sampler);
+ memcpy(constants.data() + offset, (void*)&device_sampler.bindless_index, sizeof(bindless_index));
+}
+
+void Primitive::set_index_buffer(Buffer* index_buffer) {
+ this->index_buffer = index_buffer;
+}
+
+void Primitive::set_scissor(int32_t x, int32_t y, uint32_t width, uint32_t height) {
+ scissor.offset.x = x;
+ scissor.offset.y = y;
+ scissor.extent.width = width;
+ scissor.extent.height = height;
+}
+
+void Primitive::set_draw_info(size_t vertex_count, off_t first_vertex, off_t vertex_offset) {
+ this->element_count = vertex_count;
+ this->first_vertex = first_vertex;
+ this->vertex_offset = vertex_offset;
+}
+
+void Primitive::render(VkCommandBuffer command_buffer) {
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
+
+ api.update_constants(command_buffer, VK_SHADER_STAGE_ALL_GRAPHICS, constant_offset, 64, (void*)&constants);
+
+ api.draw(
+ command_buffer,
+ pipeline,
+ index_buffer->device_buffer,
+ element_count,
+ first_vertex,
+ vertex_offset
+ );
+};
+
+
+PrimitiveRenderpass::PrimitiveRenderpass(vkapi& api)
+ : Renderpass(api) {
+ };
+
+void PrimitiveRenderpass::add_primitive(Primitive* new_primitive) {
+ primitives.push_back(new_primitive);
+}
+
+void PrimitiveRenderpass::add_color_attachment(VkFormat format) {
+ color_attachments_format.push_back(format);
+}
+
+void PrimitiveRenderpass::set_viewport(float x, float y, float width, float height) {
+ viewport.x = x;
+ viewport.y = y;
+ viewport.width = width;
+ viewport.height = height;
+}
+
+void PrimitiveRenderpass::set_color_attachment(uint32_t index, Texture* attachment) {
+ auto device_image = api.get_image(attachment->device_image);
+
+ if (device_image.size.width != framebuffers[0].size.width ||
+ device_image.size.height != framebuffers[0].size.height) {
+ recreate_framebuffers();
+ }
+
+
+ color_attachments[index] = attachment;
+ color_attachments_view[index] = device_image.view;
+}
+
+void PrimitiveRenderpass::finalize_render_pass() {
+ render_pass = api.create_render_pass(color_attachments_format, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+
+ create_framebuffers();
+
+ color_attachments.resize(color_attachments_format.size());
+ color_attachments_view.resize(color_attachments_format.size());
+}
+
+void PrimitiveRenderpass::execute(vkrenderer& renderer, VkCommandBuffer command_buffer) {
+ VkExtent2D extent = { .width = (uint32_t)viewport.width, .height = (uint32_t)viewport.height };
+
+ for (auto& attachment : color_attachments) {
+ api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, attachment->device_image);
+ }
+
+
+ api.begin_render_pass(command_buffer, render_pass, color_attachments_view, framebuffers[renderer.frame_index()], extent);
+
+ vkCmdSetViewport(command_buffer, 0, 1, &viewport);
+
+ for (auto primitive : primitives) {
+ primitive->render(command_buffer);
+ }
+
+ api.end_render_pass(command_buffer);
+
+ primitives.clear();
+}
+
+void PrimitiveRenderpass::create_framebuffers() {
+ VkExtent2D size { .width = (uint32_t) viewport.width, .height = (uint32_t) viewport.height };
+
+ for(auto& framebuffer : framebuffers) {
+ framebuffer = api.create_framebuffer(render_pass, color_attachments_format, size);
+ }
+}
+
+void PrimitiveRenderpass::recreate_framebuffers() {
+ for (auto& framebuffer: framebuffers) {
+ api.destroy_framebuffer(framebuffer);
+ }
+
+ create_framebuffers();
+}
diff --git a/src/scene.cpp b/src/scene.cpp
index 44c8f8e..871ba68 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -124,23 +124,23 @@ scene::scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer)
// bvh builder(spheres, packed_nodes);
scene_buffer = renderer.create_buffer(sizeof(meta), false);
- std::memcpy(scene_buffer->ptr(), &meta, sizeof(meta));
+ renderer.update_buffer(scene_buffer, &meta, 0, sizeof(meta));
indices_buffer = renderer.create_buffer(indices.size() * sizeof(indices[0]), true);
- std::memcpy(indices_buffer->ptr(), indices.data(), indices.size() * sizeof(indices[0]));
+ renderer.update_buffer(indices_buffer, indices.data(), 0, indices.size() * sizeof(indices[0]));
positions_buffer = renderer.create_buffer(positions.size() * sizeof(positions[0]), true);
- std::memcpy(positions_buffer->ptr(), positions.data(), positions.size() * sizeof(positions[0]));
+ renderer.update_buffer(positions_buffer, positions.data(), 0, positions.size() * sizeof(positions[0]));
normals_buffer = renderer.create_buffer(normals.size() * sizeof(normals[0]), true);
- std::memcpy(normals_buffer->ptr(), normals.data(), normals.size() * sizeof(normals[0]));
+ renderer.update_buffer(normals_buffer, normals.data(), 0, normals.size() * sizeof(normals[0]));
uvs_buffer = renderer.create_buffer(uvs.size() * sizeof(uvs[0]), true);
- std::memcpy(uvs_buffer->ptr(), uvs.data(), uvs.size() * sizeof(uvs[0]));
+ renderer.update_buffer(uvs_buffer, uvs.data(), 0, uvs.size() * sizeof(uvs[0]));
bvh_buffer = renderer.create_buffer(packed_nodes.size() * sizeof(packed_nodes[0]), true);
- std::memcpy(bvh_buffer->ptr(), packed_nodes.data(), packed_nodes.size() * sizeof(packed_nodes[0]));
+ renderer.update_buffer(bvh_buffer, packed_nodes.data(), 0, packed_nodes.size() * sizeof(packed_nodes[0]));
materials_buffer = renderer.create_buffer(materials.size() * sizeof(materials[0]), true);
- std::memcpy(materials_buffer->ptr(), materials.data(), materials.size() * sizeof(materials[0]));
+ renderer.update_buffer(materials_buffer, materials.data(), 0, materials.size() * sizeof(materials[0]));
}
diff --git a/src/vk-api.cpp b/src/vk-api.cpp
index 0d26e49..1000079 100644
--- a/src/vk-api.cpp
+++ b/src/vk-api.cpp
@@ -2,6 +2,7 @@
#include <memory>
#include "vk-api.hpp"
+#include "vulkan-loader.hpp"
#include "window.hpp"
#include "utils.hpp"
@@ -100,15 +101,20 @@ vkapi::vkapi() {
.size = 64,
},
{
- .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
+ .stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS,
.offset = 64,
- .size = 32,
- },
- {
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
- .offset = 96,
- .size = 32,
+ .size = 64,
},
+ // {
+ // .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
+ // .offset = 64,
+ // .size = 32,
+ // },
+ // {
+ // .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
+ // .offset = 96,
+ // .size = 32,
+ // },
};
VkPipelineLayoutCreateInfo layout_create_info = {};
@@ -135,15 +141,17 @@ vkapi::vkapi() {
vkapi::~vkapi() {
// Free resources
- while (buffers.empty()) {
- destroy_buffer(buffers.begin()->second);
+ for (handle buffer_handle = 0; buffer_handle < buffers.size(); buffer_handle++) {
+ destroy_buffer(buffer_handle);
}
- while (images.empty())
- destroy_image(images.begin()->second);
+ for (handle image_handle = 0; image_handle < images.size(); image_handle++) {
+ destroy_image(image_handle);
+ }
- while (samplers.empty())
- destroy_sampler(samplers.begin()->second);
+ for(handle sampler_handle = 0; sampler_handle < samplers.size(); sampler_handle++) {
+ destroy_sampler(sampler_handle);
+ }
// Free bindless descriptor stuff
vkDestroyDescriptorSetLayout(context.device, bindless_descriptor.set_layout, nullptr);
@@ -155,8 +163,8 @@ vkapi::~vkapi() {
}
-buffer vkapi::create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, VmaMemoryUsage mem_usage) {
- buffer buffer = {};
+handle vkapi::create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, VmaMemoryUsage mem_usage) {
+ struct buffer* buffer = new struct buffer();
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@@ -167,34 +175,36 @@ buffer vkapi::create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, V
alloc_create_info.usage = mem_usage;
alloc_create_info.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
- VKRESULT(vmaCreateBuffer(context.allocator, &buffer_info, &alloc_create_info, &buffer.handle, &buffer.alloc, &buffer.alloc_info))
+ VKRESULT(vmaCreateBuffer(context.allocator, &buffer_info, &alloc_create_info, &buffer->handle, &buffer->alloc, &buffer->alloc_info))
VkBufferDeviceAddressInfo buffer_device_address_info = {};
buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
buffer_device_address_info.pNext = VK_NULL_HANDLE;
- buffer_device_address_info.buffer = buffer.handle;
+ buffer_device_address_info.buffer = buffer->handle;
- buffer.size = data_size;
+ buffer->size = data_size;
- buffer.device_address = vkGetBufferDeviceAddress(context.device, &buffer_device_address_info);
+ buffer->device_address = vkGetBufferDeviceAddress(context.device, &buffer_device_address_info);
- buffers.insert({ buffer.handle, buffer });
+ buffers.push_back(buffer);
- return std::move(buffer);
+ return buffers.size() - 1;
}
-void vkapi::copy_buffer(VkCommandBuffer cmd_buf, buffer src, buffer dst, size_t size) {
+void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, size_t size) {
VkBufferCopy buffer_copy = {};
buffer_copy.srcOffset = 0;
buffer_copy.dstOffset = 0;
buffer_copy.size = size;
- vkCmdCopyBuffer(cmd_buf, src.handle, dst.handle, 1, &buffer_copy);
+ vkCmdCopyBuffer(cmd_buf, buffers[src]->handle, buffers[dst]->handle, 1, &buffer_copy);
}
-void vkapi::copy_buffer(VkCommandBuffer cmd_buf, buffer src, image dst) {
+void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst) {
+ auto& dst_image = images[dst];
+
VkImageSubresourceLayers image_subresource_layers = {};
- image_subresource_layers.aspectMask = dst.subresource_range.aspectMask;
+ image_subresource_layers.aspectMask = dst_image->subresource_range.aspectMask;
image_subresource_layers.mipLevel = 0;
image_subresource_layers.baseArrayLayer = 0;
image_subresource_layers.layerCount = 1;
@@ -205,28 +215,29 @@ void vkapi::copy_buffer(VkCommandBuffer cmd_buf, buffer src, image dst) {
buffer_to_image_copy.bufferImageHeight = 0;
buffer_to_image_copy.imageSubresource = image_subresource_layers;
buffer_to_image_copy.imageOffset = { 0, 0, 0 };
- buffer_to_image_copy.imageExtent = dst.size;
+ buffer_to_image_copy.imageExtent = dst_image->size;
- vkCmdCopyBufferToImage(cmd_buf, src.handle, dst.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_to_image_copy);
+ vkCmdCopyBufferToImage(cmd_buf, buffers[src]->handle, dst_image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_to_image_copy);
}
-void vkapi::destroy_buffer(buffer& buffer) {
- vmaDestroyBuffer(context.allocator, buffer.handle, buffer.alloc);
+void vkapi::destroy_buffer(handle buffer) {
+ vmaDestroyBuffer(context.allocator, buffers[buffer]->handle, buffers[buffer]->alloc);
- buffers.erase(buffer.handle);
+ // TODO: Free the element once using freelists
+ // buffers.erase(buffer.handle);
}
-image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages) {
- image image;
+handle vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages) {
+ struct image* image = new struct image();
- image.size = size;
+ image->size = size;
- image.subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- image.subresource_range.baseMipLevel = 0;
- image.subresource_range.levelCount = 1;
- image.subresource_range.baseArrayLayer = 0;
- image.subresource_range.layerCount = 1;
+ image->subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ image->subresource_range.baseMipLevel = 0;
+ image->subresource_range.levelCount = 1;
+ image->subresource_range.baseArrayLayer = 0;
+ image->subresource_range.layerCount = 1;
VkImageCreateInfo img_create_info = {};
img_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -248,13 +259,13 @@ image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags us
VmaAllocationCreateInfo alloc_create_info = {};
alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;
- VKRESULT(vmaCreateImage(context.allocator, &img_create_info, &alloc_create_info, &image.handle, &image.alloc, &image.alloc_info))
+ VKRESULT(vmaCreateImage(context.allocator, &img_create_info, &alloc_create_info, &image->handle, &image->alloc, &image->alloc_info))
VkImageViewCreateInfo image_view_create_info = {};
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_create_info.pNext = nullptr;
image_view_create_info.flags = 0;
- image_view_create_info.image = image.handle;
+ image_view_create_info.image = image->handle;
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_create_info.format = format;
image_view_create_info.components = {
@@ -263,41 +274,54 @@ image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags us
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY
};
- image_view_create_info.subresourceRange = image.subresource_range;
+ image_view_create_info.subresourceRange = image->subresource_range;
- VKRESULT(vkCreateImageView(context.device, &image_view_create_info, VK_NULL_HANDLE, &image.view))
+ VKRESULT(vkCreateImageView(context.device, &image_view_create_info, VK_NULL_HANDLE, &image->view))
- image.bindless_storage_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- image.bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ image->usages = usages;
- images.insert({ image.handle, image });
+ images.push_back(image);
- return std::move(image);
+ auto image_handle = images.size() - 1;
+
+ if (usages & VK_IMAGE_USAGE_STORAGE_BIT) {
+ image->bindless_storage_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ update_descriptor_image(image_handle, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ }
+
+ if (usages & VK_IMAGE_USAGE_SAMPLED_BIT) {
+ image->bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ update_descriptor_image(image_handle, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ }
+
+ return image_handle;
}
-void vkapi::destroy_image(image &image) {
- bindless_descriptor.free(image.bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- bindless_descriptor.free(image.bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+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);
- vmaDestroyImage(context.allocator, image.handle, image.alloc);
- vkDestroyImageView(context.device, image.view, nullptr);
+ vmaDestroyImage(context.allocator, current_image->handle, current_image->alloc);
+ vkDestroyImageView(context.device, current_image->view, nullptr);
- images.erase(image.handle);
+ // TODO: Free once using freelist
+ // images.erase(image.handle);
}
-std::vector<image> vkapi::create_images(VkExtent3D size, VkFormat format, VkImageUsageFlags usages, size_t image_count) {
- std::vector<image> images { image_count };
+std::vector<handle> vkapi::create_images(VkExtent3D size, VkFormat format, VkImageUsageFlags usages, size_t image_count) {
+ std::vector<handle> images_handles(image_count);
for (size_t image_index = 0; image_index < image_count; image_index++) {
- images[image_index] = create_image(size, format, usages);
+ images_handles[image_index] = create_image(size, format, usages);
}
- return std::move(images);
+ return std::move(images_handles);
}
-void vkapi::destroy_images(std::vector<image> &images) {
- for (auto &image: images) {
- destroy_image(image);
+void vkapi::destroy_images(std::vector<handle> &images) {
+ for (auto handle: images) {
+ destroy_image(handle);
}
}
@@ -368,7 +392,7 @@ void vkapi::destroy_semaphores(std::vector<VkSemaphore> &semaphores) {
}
-sampler vkapi::create_sampler(VkFilter filter, VkSamplerAddressMode address_mode) {
+handle vkapi::create_sampler(VkFilter filter, VkSamplerAddressMode address_mode) {
VkSamplerCreateInfo sampler_create_info = {};
sampler_create_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
sampler_create_info.pNext = VK_NULL_HANDLE;
@@ -388,22 +412,26 @@ sampler vkapi::create_sampler(VkFilter filter, VkSamplerAddressMode address_mode
sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
sampler_create_info.unnormalizedCoordinates = VK_FALSE;
- sampler sampler;
- VKRESULT(vkCreateSampler(context.device, &sampler_create_info, VK_NULL_HANDLE, &sampler.handle))
+ struct sampler* sampler = new struct sampler();
+ VKRESULT(vkCreateSampler(context.device, &sampler_create_info, VK_NULL_HANDLE, &sampler->handle))
+
+ sampler->bindless_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLER);
- sampler.bindless_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLER);
- samplers.insert({ sampler.handle, sampler });
+ samplers.push_back(sampler);
- return std::move(sampler);
+ update_descriptor_sampler(samplers.size() - 1);
+
+ return samplers.size() - 1;
}
-void vkapi::destroy_sampler(sampler sampler) {
- bindless_descriptor.free(sampler.bindless_index, VK_DESCRIPTOR_TYPE_SAMPLER);
+void vkapi::destroy_sampler(handle sampler) {
+ auto current_sampler = samplers[sampler];
+ bindless_descriptor.free(current_sampler->bindless_index, VK_DESCRIPTOR_TYPE_SAMPLER);
- vkDestroySampler(context.device, sampler.handle, VK_NULL_HANDLE);
+ vkDestroySampler(context.device, current_sampler->handle, VK_NULL_HANDLE);
- samplers.erase(sampler.handle);
+ // samplers.erase(sampler.handle);
}
@@ -437,12 +465,13 @@ VkRenderPass vkapi::create_render_pass(std::vector<VkFormat>& color_attachments_
attachment_description.flags = 0;
attachment_description.format = format;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
- attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // TODO: Set based on render pass usage
+ attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // TODO: Set based on render pass usage
+
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment_description.initialLayout = initial_layout;
- attachment_description.finalLayout = initial_layout;
+ attachment_description.finalLayout = final_layout;
attachments_description.push_back(attachment_description);
@@ -463,6 +492,29 @@ VkRenderPass vkapi::create_render_pass(std::vector<VkFormat>& color_attachments_
subpass_description.preserveAttachmentCount = 0;
subpass_description.pPreserveAttachments = VK_NULL_HANDLE;
+
+
+ VkSubpassDependency subpass_dependency[2] = {};
+ subpass_dependency[0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_dependency[0].dstSubpass = 1; // First subpass attachment is used in
+ subpass_dependency[0].srcStageMask = VK_PIPELINE_STAGE_NONE_KHR;
+ subpass_dependency[0].dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
+ subpass_dependency[0].srcAccessMask = 0;
+ subpass_dependency[0].dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_dependency[0].dependencyFlags = 0;
+
+
+ subpass_dependency[1].srcSubpass = 1; // Last subpass attachment is used in
+ subpass_dependency[1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ subpass_dependency[1].srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
+ subpass_dependency[1].dstStageMask = VK_PIPELINE_STAGE_NONE_KHR;
+ subpass_dependency[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ subpass_dependency[1].dstAccessMask = 0;
+ subpass_dependency[1].dependencyFlags = 0;
+
+
VkRenderPass render_pass;
VkRenderPassCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
@@ -472,9 +524,8 @@ VkRenderPass vkapi::create_render_pass(std::vector<VkFormat>& color_attachments_
create_info.pAttachments = attachments_description.data();
create_info.subpassCount = 1;
create_info.pSubpasses = &subpass_description;
- // TODO: Use this to chain renderpasses
- create_info.dependencyCount = 0;
- create_info.pDependencies = VK_NULL_HANDLE;
+ // create_info.dependencyCount = sizeof(subpass_dependency) / sizeof(VkSubpassDependency);
+ // create_info.pDependencies = subpass_dependency;
VKRESULT(vkCreateRenderPass(context.device, &create_info, VK_NULL_HANDLE, &render_pass))
@@ -486,46 +537,68 @@ void vkapi::destroy_render_pass(VkRenderPass render_pass) {
}
-VkFramebuffer vkapi::create_framebuffer(VkRenderPass render_pass, std::vector<image>& images, VkExtent2D size) {
- VkFramebuffer framebuffer;
- std::vector<VkImageView> attachements;
- for (auto& image: images) {
- attachements.push_back(image.view);
+framebuffer vkapi::create_framebuffer(VkRenderPass render_pass, std::vector<VkFormat>& formats, VkExtent2D size) {
+ VkFramebuffer framebuffer_handle;
+
+ std::vector<VkFramebufferAttachmentImageInfo> attachments_image_infos(formats.size());
+ for (size_t index = 0; index < formats.size(); index++) {
+ VkFramebufferAttachmentImageInfo attachments_image_info = {};
+ attachments_image_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;
+ attachments_image_info.pNext = VK_NULL_HANDLE;
+ attachments_image_info.flags = 0;
+ attachments_image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ attachments_image_info.width = size.width;
+ attachments_image_info.height = size.height;
+ attachments_image_info.layerCount = 1;
+ attachments_image_info.viewFormatCount = 1;
+ attachments_image_info.pViewFormats = &formats[index];
+
+ attachments_image_infos[index] = attachments_image_info;
}
+ VkFramebufferAttachmentsCreateInfo attachments_create_info = {};
+ attachments_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO;
+ attachments_create_info.pNext = VK_NULL_HANDLE;
+ attachments_create_info.attachmentImageInfoCount = attachments_image_infos.size();
+ attachments_create_info.pAttachmentImageInfos = attachments_image_infos.data();
+
VkFramebufferCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- create_info.pNext = VK_NULL_HANDLE;
- create_info.flags = 0;
+ create_info.pNext = &attachments_create_info;
+ create_info.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
create_info.renderPass = render_pass;
- create_info.attachmentCount = attachements.size();
- create_info.pAttachments = attachements.data();
+ create_info.attachmentCount = formats.size();
+ create_info.pAttachments = VK_NULL_HANDLE;
create_info.width = size.width;
create_info.height = size.height;
create_info.layers = 1;
- VKRESULT(vkCreateFramebuffer(context.device, &create_info, VK_NULL_HANDLE, &framebuffer))
+ VKRESULT(vkCreateFramebuffer(context.device, &create_info, VK_NULL_HANDLE, &framebuffer_handle))
- return framebuffer;
+ return { .handle = framebuffer_handle, .size = size };
}
-std::vector<VkFramebuffer> vkapi::create_framebuffers(VkRenderPass render_pass, std::vector<image>& images, VkExtent2D size, uint32_t framebuffer_count) {
- std::vector<VkFramebuffer> framebuffers { framebuffer_count };
+std::vector<framebuffer> vkapi::create_framebuffers(VkRenderPass render_pass, std::vector<VkFormat>& formats, VkExtent2D size, uint32_t framebuffer_count) {
+ std::vector<framebuffer> framebuffers { framebuffer_count };
for (auto& framebuffer: framebuffers) {
- framebuffer = create_framebuffer(render_pass, images, size);
+ framebuffer = create_framebuffer(render_pass, formats, size);
}
return std::move(framebuffers);
}
-void vkapi::destroy_framebuffer(VkFramebuffer framebuffer) {
- vkDestroyFramebuffer(context.device, framebuffer, VK_NULL_HANDLE);
+void vkapi::destroy_framebuffer(framebuffer framebuffer) {
+ VKRESULT(vkDeviceWaitIdle(context.device))
+
+ vkDestroyFramebuffer(context.device, framebuffer.handle, VK_NULL_HANDLE);
}
-void vkapi::destroy_framebuffers(std::vector<VkFramebuffer>& framebuffers) {
+void vkapi::destroy_framebuffers(std::vector<framebuffer>& framebuffers) {
+ VKRESULT(vkDeviceWaitIdle(context.device))
+
for (auto& framebuffer: framebuffers) {
- vkDestroyFramebuffer(context.device, framebuffer, VK_NULL_HANDLE);
+ vkDestroyFramebuffer(context.device, framebuffer.handle, VK_NULL_HANDLE);
}
}
@@ -781,10 +854,11 @@ void vkapi::destroy_surface(VkSurfaceKHR surface) {
swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count, VkImageUsageFlags usages, VkSwapchainKHR old_swapchain) {
swapchain swapchain;
+
VkBool32 queue_support_presentation = VK_FALSE;
VKRESULT(vkGetPhysicalDeviceSurfaceSupportKHR(context.physical_device, context.queue_index, surface, &queue_support_presentation))
- assert(queue_support_presentation == true);
+ assert(queue_support_presentation == VK_TRUE);
VkSurfaceCapabilitiesKHR caps;
VKRESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context.physical_device, surface, &caps))
@@ -803,18 +877,21 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
swapchain.extent.height = caps.maxImageExtent.height;
}
+
uint32_t supported_formats_count = 0;
VKRESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(context.physical_device, surface, &supported_formats_count, VK_NULL_HANDLE))
std::vector<VkSurfaceFormatKHR> supported_formats { supported_formats_count };
VKRESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(context.physical_device, surface, &supported_formats_count, supported_formats.data()))
+
uint32_t supported_present_modes_count = 0;
VKRESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(context.physical_device, surface, &supported_present_modes_count, VK_NULL_HANDLE))
std::vector<VkPresentModeKHR> supported_present_modes { supported_present_modes_count };
VKRESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(context.physical_device, surface, &supported_present_modes_count, supported_present_modes.data()))
+
swapchain.surface_format = supported_formats[0];
VkSwapchainCreateInfoKHR create_info = {};
@@ -831,22 +908,20 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
create_info.preTransform = caps.currentTransform;
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
- // create_info.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
+ create_info.presentMode = supported_present_modes[0];
create_info.clipped = VK_TRUE;
create_info.oldSwapchain = old_swapchain;
VKRESULT(vkCreateSwapchainKHR(context.device, &create_info, nullptr, &swapchain.handle))
- uint32_t image_count = 0;
- VKRESULT(vkGetSwapchainImagesKHR(context.device, swapchain.handle, &image_count, VK_NULL_HANDLE))
- swapchain.image_count = image_count;
- swapchain.images = std::vector<image>{ swapchain.image_count };
- auto images = std::vector<VkImage>{ swapchain.image_count };
- auto views = std::vector<VkImageView>{ swapchain.image_count };
+ VKRESULT(vkGetSwapchainImagesKHR(context.device, swapchain.handle, &swapchain.image_count, VK_NULL_HANDLE))
+
+ swapchain.images = std::vector<handle>(swapchain.image_count);
+ auto vk_images = std::vector<VkImage>(swapchain.image_count);
+
+ VKRESULT(vkGetSwapchainImagesKHR(context.device, swapchain.handle, &swapchain.image_count, vk_images.data()))
- VKRESULT(vkGetSwapchainImagesKHR(context.device, swapchain.handle, (uint32_t*)&swapchain.image_count, images.data()))
VkImageSubresourceRange image_subresource_range = {};
image_subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -862,18 +937,19 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
};
for (size_t image_index = 0; image_index < swapchain.image_count; image_index++) {
- swapchain.images[image_index].bindless_storage_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- swapchain.images[image_index].bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ struct image* current_image = new struct image();
+
+ current_image->handle = vk_images[image_index];
+ current_image->size = image_size;
+ current_image->subresource_range = image_subresource_range;
+ current_image->usages = usages;
- swapchain.images[image_index].handle = images[image_index];
- swapchain.images[image_index].size = image_size;
- swapchain.images[image_index].subresource_range = image_subresource_range;
VkImageViewCreateInfo image_view_create_info = {};
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_create_info.pNext = nullptr;
image_view_create_info.flags = 0;
- image_view_create_info.image = swapchain.images[image_index].handle;
+ image_view_create_info.image = current_image->handle;
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_create_info.format = swapchain.surface_format.format;
image_view_create_info.components = {
@@ -882,38 +958,58 @@ swapchain vkapi::create_swapchain(VkSurfaceKHR surface, size_t min_image_count,
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY
};
- image_view_create_info.subresourceRange = image_subresource_range;
+ image_view_create_info.subresourceRange = image_subresource_range;
+
+ VKRESULT(vkCreateImageView(context.device, &image_view_create_info, nullptr, &current_image->view))
+
+ images.push_back(current_image);
- VKRESULT(vkCreateImageView(context.device, &image_view_create_info, nullptr, &swapchain.images[image_index].view))
+ auto current_image_handle = images.size() - 1;
+
+ if (usages & VK_IMAGE_USAGE_STORAGE_BIT) {
+ 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) {
+ current_image->bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ update_descriptor_image(current_image_handle, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ }
+
+ swapchain.images[image_index] = current_image_handle;
}
- return std::move(swapchain);
+ return swapchain;
}
void vkapi::destroy_swapchain(swapchain& swapchain) {
+ VKRESULT(vkDeviceWaitIdle(context.device))
+
for(auto &image: swapchain.images) {
- bindless_descriptor.free(image.bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- bindless_descriptor.free(image.bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+ bindless_descriptor.free(images[image]->bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
+ bindless_descriptor.free(images[image]->bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
- vkDestroyImageView(context.device, image.view, nullptr);
+ vkDestroyImageView(context.device, images[image]->view, nullptr);
}
vkDestroySwapchainKHR(context.device, swapchain.handle, nullptr);
}
-void vkapi::update_descriptor_image(image &img, VkDescriptorType type) {
+void vkapi::update_descriptor_image(handle img, VkDescriptorType type) {
VkDescriptorImageInfo descriptor_image_info;
VkWriteDescriptorSet write_descriptor;
+ auto current_image = images[img];
+
descriptor_image_info.sampler = VK_NULL_HANDLE;
- descriptor_image_info.imageView = img.view;
+ descriptor_image_info.imageView = current_image->view;
descriptor_image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor.pNext = nullptr;
write_descriptor.dstSet = bindless_descriptor.set;
write_descriptor.dstBinding = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 2 : 1;
- write_descriptor.dstArrayElement = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? img.bindless_storage_index : img.bindless_sampled_index;
+ write_descriptor.dstArrayElement = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? current_image->bindless_storage_index : current_image->bindless_sampled_index;
write_descriptor.descriptorCount = 1;
write_descriptor.descriptorType = type;
write_descriptor.pImageInfo = &descriptor_image_info;
@@ -923,21 +1019,21 @@ void vkapi::update_descriptor_image(image &img, VkDescriptorType type) {
vkUpdateDescriptorSets(context.device, 1, &write_descriptor, 0, nullptr);
}
-void vkapi::update_descriptor_images(std::vector<image> &images, VkDescriptorType type) {
+void vkapi::update_descriptor_images(std::vector<handle> &handles, VkDescriptorType type) {
std::vector<VkDescriptorImageInfo> descriptor_images_info { images.size() };
std::vector<VkWriteDescriptorSet> writes_descriptor { images.size() };
for (size_t image_index = 0; image_index < images.size(); image_index++) {
- auto &image = images[image_index];
+ auto image = images[handles[image_index]];
descriptor_images_info[image_index].sampler = VK_NULL_HANDLE;
- descriptor_images_info[image_index].imageView = image.view;
+ descriptor_images_info[image_index].imageView = image->view;
descriptor_images_info[image_index].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
writes_descriptor[image_index].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes_descriptor[image_index].pNext = nullptr;
writes_descriptor[image_index].dstSet = bindless_descriptor.set;
writes_descriptor[image_index].dstBinding = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 2 : 1;
- writes_descriptor[image_index].dstArrayElement = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? image.bindless_storage_index : image.bindless_sampled_index;
+ writes_descriptor[image_index].dstArrayElement = type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? image->bindless_storage_index : image->bindless_sampled_index;
writes_descriptor[image_index].descriptorCount = 1;
writes_descriptor[image_index].descriptorType = type;
writes_descriptor[image_index].pImageInfo = &descriptor_images_info[image_index];
@@ -948,11 +1044,12 @@ void vkapi::update_descriptor_images(std::vector<image> &images, VkDescriptorTyp
vkUpdateDescriptorSets(context.device, writes_descriptor.size(), writes_descriptor.data(), 0, nullptr);
}
-void vkapi::update_descriptor_sampler(sampler &sampler) {
+void vkapi::update_descriptor_sampler(handle sampler) {
VkDescriptorImageInfo descriptor_image_info;
VkWriteDescriptorSet write_descriptor;
+ auto current_sampler = samplers[sampler];
- descriptor_image_info.sampler = sampler.handle;
+ descriptor_image_info.sampler = current_sampler->handle;
descriptor_image_info.imageView = VK_NULL_HANDLE;
descriptor_image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -960,7 +1057,7 @@ void vkapi::update_descriptor_sampler(sampler &sampler) {
write_descriptor.pNext = nullptr;
write_descriptor.dstSet = bindless_descriptor.set;
write_descriptor.dstBinding = 0;
- write_descriptor.dstArrayElement = sampler.bindless_index;
+ write_descriptor.dstArrayElement = current_sampler->bindless_index;
write_descriptor.descriptorCount = 1;
write_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
write_descriptor.pImageInfo = &descriptor_image_info;
@@ -970,12 +1067,13 @@ void vkapi::update_descriptor_sampler(sampler &sampler) {
vkUpdateDescriptorSets(context.device, 1, &write_descriptor, 0, nullptr);
}
-void vkapi::update_descriptor_samplers(std::vector<sampler> &samplers) {
+void vkapi::update_descriptor_samplers(std::vector<handle> &handles) {
std::vector<VkDescriptorImageInfo> descriptor_images_info { samplers.size() };
std::vector<VkWriteDescriptorSet> writes_descriptor { samplers.size() };
for (size_t sampler_index = 0; sampler_index < samplers.size(); sampler_index++) {
- descriptor_images_info[sampler_index].sampler = samplers[sampler_index].handle;
+ auto sampler = samplers[handles[sampler_index]];
+ descriptor_images_info[sampler_index].sampler = sampler->handle;
descriptor_images_info[sampler_index].imageView = VK_NULL_HANDLE;
descriptor_images_info[sampler_index].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
@@ -983,7 +1081,7 @@ void vkapi::update_descriptor_samplers(std::vector<sampler> &samplers) {
writes_descriptor[sampler_index].pNext = nullptr;
writes_descriptor[sampler_index].dstSet = bindless_descriptor.set;
writes_descriptor[sampler_index].dstBinding = 0;
- writes_descriptor[sampler_index].dstArrayElement = samplers[sampler_index].bindless_index;
+ writes_descriptor[sampler_index].dstArrayElement = sampler->bindless_index;
writes_descriptor[sampler_index].descriptorCount = 1;
writes_descriptor[sampler_index].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
writes_descriptor[sampler_index].pImageInfo = &descriptor_images_info[sampler_index];
@@ -1008,22 +1106,24 @@ void vkapi::start_record(VkCommandBuffer command_buffer) {
vkBeginCommandBuffer(command_buffer, &cmd_buf_begin_info);
}
-void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, image& image) {
+void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, handle 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 = image.previous_access;
+ undefined_to_general_barrier.srcAccessMask = current_image->previous_access;
undefined_to_general_barrier.dstAccessMask = dst_access;
- undefined_to_general_barrier.oldLayout = image.previous_layout;
+ 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 = image.handle;
- undefined_to_general_barrier.subresourceRange = image.subresource_range;
+ undefined_to_general_barrier.image = current_image->handle;
+ undefined_to_general_barrier.subresourceRange = current_image->subresource_range;
vkCmdPipelineBarrier(
command_buffer,
- image.previous_stage,
+ current_image->previous_stage,
dst_stage,
0,
0,
@@ -1034,13 +1134,13 @@ void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layo
&undefined_to_general_barrier
);
- image.previous_layout = dst_layout;
- image.previous_access = dst_access;
- image.previous_stage = dst_stage;
+ current_image->previous_layout = dst_layout;
+ current_image->previous_access = dst_access;
+ current_image->previous_stage = dst_stage;
}
-void vkapi::begin_render_pass(VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D size, pipeline& pipeline) {
+void vkapi::begin_render_pass(VkCommandBuffer command_buffer, VkRenderPass render_pass, std::vector<VkImageView>& attachments, framebuffer framebuffer, VkExtent2D size) {
VkRect2D render_area = {
{
0,
@@ -1049,18 +1149,23 @@ void vkapi::begin_render_pass(VkCommandBuffer command_buffer, VkRenderPass rende
size
};
+ VkRenderPassAttachmentBeginInfo attachment_begin_info = {};
+ attachment_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO;
+ attachment_begin_info.pNext = VK_NULL_HANDLE;
+ attachment_begin_info.attachmentCount = attachments.size();
+ attachment_begin_info.pAttachments = attachments.data();
+
VkClearValue clear_value = { 0.f, 0.f, 0.f, 1.f };
VkRenderPassBeginInfo render_pass_begin_info = {};
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- render_pass_begin_info.pNext = VK_NULL_HANDLE;
+ render_pass_begin_info.pNext = &attachment_begin_info;
render_pass_begin_info.renderPass = render_pass;
- render_pass_begin_info.framebuffer = framebuffer;
+ render_pass_begin_info.framebuffer = framebuffer.handle;
render_pass_begin_info.renderArea = render_area;
render_pass_begin_info.clearValueCount = 1;
render_pass_begin_info.pClearValues = &clear_value;
vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
- vkCmdBindPipeline(command_buffer, pipeline.bind_point, pipeline.handle);
}
void vkapi::end_render_pass(VkCommandBuffer command_buffer) {
@@ -1083,14 +1188,18 @@ void vkapi::draw(VkCommandBuffer command_buffer, pipeline& pipeline, uint32_t ve
vkCmdDraw(command_buffer, vertex_count, 1, vertex_offset, 0);
}
-void vkapi::draw(VkCommandBuffer command_buffer, pipeline& pipeline, buffer& index_buffer, uint32_t index_count, uint32_t index_offset, uint32_t vertex_offset) {
- vkCmdBindIndexBuffer(command_buffer, index_buffer.handle, 0, VK_INDEX_TYPE_UINT16);
+void vkapi::draw(VkCommandBuffer command_buffer, pipeline& pipeline, handle index_buffer, uint32_t index_count, uint32_t index_offset, uint32_t vertex_offset) {
+ vkCmdBindIndexBuffer(command_buffer, buffers[index_buffer]->handle, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless_descriptor.pipeline_layout, 0, 1, &bindless_descriptor.set, 0, nullptr);
+ vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.handle);
vkCmdDrawIndexed(command_buffer, index_count, 1, index_offset, vertex_offset, 0);
}
-void vkapi::blit_full(VkCommandBuffer command_buffer, image& src_image, image& dst_image) {
+void vkapi::blit_full(VkCommandBuffer command_buffer, handle src, handle dst) {
+ auto src_image = images[src];
+ auto dst_image = images[dst];
+
VkImageSubresourceLayers images_subres_layers {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
@@ -1104,9 +1213,9 @@ void vkapi::blit_full(VkCommandBuffer command_buffer, image& src_image, image& d
.z = 0,
};
VkOffset3D end_offset {
- .x = (int32_t)src_image.size.width,
- .y = (int32_t)src_image.size.height,
- .z = (int32_t)src_image.size.depth,
+ .x = (int32_t)src_image->size.width,
+ .y = (int32_t)src_image->size.height,
+ .z = (int32_t)src_image->size.depth,
};
VkImageBlit blit_region {
@@ -1116,7 +1225,7 @@ void vkapi::blit_full(VkCommandBuffer command_buffer, image& src_image, image& d
.dstOffsets = { start_offset, end_offset },
};
- vkCmdBlitImage(command_buffer, src_image.handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST);
+ vkCmdBlitImage(command_buffer, src_image->handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit_region, VK_FILTER_NEAREST);
}
void vkapi::end_record(VkCommandBuffer command_buffer) {
diff --git a/src/vk-context.cpp b/src/vk-context.cpp
index b539194..53f3e59 100644
--- a/src/vk-context.cpp
+++ b/src/vk-context.cpp
@@ -3,7 +3,6 @@
#include "vk-context.hpp"
#include "vulkan-loader.hpp"
-#include "vulkan/vulkan_core.h"
#define VMA_IMPLEMENTATION
#include "thirdparty/vk_mem_alloc.h"
@@ -129,6 +128,7 @@ void vkcontext::create_device() {
physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE;
physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE;
physical_device_12_features.descriptorBindingUpdateUnusedWhilePending = VK_TRUE;
+ physical_device_12_features.imagelessFramebuffer = VK_TRUE;
VkPhysicalDeviceFeatures2 device_features = {};
device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@@ -249,7 +249,7 @@ void vkcontext::check_available_instance_extensions(std::vector<const char*>& av
}
}
- assert(available_needed_extensions_count == needed_extensions.size());
+ // assert(available_needed_extensions_count == needed_extensions.size());
}
bool vkcontext::support_required_features(VkPhysicalDevice physical_device) {
@@ -272,7 +272,8 @@ bool vkcontext::support_required_features(VkPhysicalDevice physical_device) {
vulkan_12_features.shaderSampledImageArrayNonUniformIndexing == VK_TRUE &&
vulkan_12_features.descriptorBindingPartiallyBound == VK_TRUE &&
vulkan_12_features.descriptorBindingPartiallyBound == VK_TRUE &&
- vulkan_12_features.descriptorBindingUpdateUnusedWhilePending == VK_TRUE) {
+ vulkan_12_features.descriptorBindingUpdateUnusedWhilePending == VK_TRUE &&
+ vulkan_12_features.imagelessFramebuffer == VK_TRUE) {
std::cerr << "Using physical device " << physical_device_properties.deviceName << std::endl;
return true;
} else {
diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp
index e2e62ff..2fcd39d 100644
--- a/src/vk-renderer.cpp
+++ b/src/vk-renderer.cpp
@@ -3,9 +3,8 @@
#include <cassert>
#include "compute-renderpass.hpp"
-#include "imgui.h"
+#include "primitive-renderpass.hpp"
#include "vk-renderer.hpp"
-#include "thirdparty/vk_mem_alloc.h"
#include "defines.hpp"
#include "window.hpp"
@@ -16,29 +15,23 @@
#define VKRESULT(result) result;
#endif
-struct VkVertex {
- float x, y;
- float u, v;
- uint32_t color;
- uint32_t padding[3];
-};
-
-struct UiTransforms {
- float scale_x, scale_y;
- float translate_x, translate_y;
-};
-
vkrenderer::vkrenderer(window& wnd) {
platform_surface = api.create_surface(wnd);
swapchain = api.create_swapchain(
platform_surface,
min_swapchain_image_count,
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT |
- VK_IMAGE_USAGE_STORAGE_BIT,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // |
+ // VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ // VK_IMAGE_USAGE_STORAGE_BIT,
VK_NULL_HANDLE
);
+ swapchain_textures.resize(swapchain.image_count);
+ for (size_t index = 0; index < swapchain.image_count; index++) {
+ swapchain_textures[index] = new Texture();
+ swapchain_textures[index]->device_image = swapchain.images[index];
+ }
+
tonemapping_pipeline = api.create_compute_pipeline("tonemapping");
command_buffers = api.create_command_buffers(virtual_frames_count);
@@ -47,83 +40,7 @@ vkrenderer::vkrenderer(window& wnd) {
execution_semaphores = api.create_semaphores(virtual_frames_count);
acquire_semaphores = api.create_semaphores(virtual_frames_count);
-
- std::vector<VkFormat> attachments_format { swapchain.surface_format.format };
- render_pass = api.create_render_pass(attachments_format, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
-
- for (auto& current_image : swapchain.images) {
- std::vector<image> attachments { current_image };
- framebuffers.push_back(api.create_framebuffer(render_pass, attachments, swapchain.extent));
- }
-
-
- std::vector<VkDynamicState> dynamic_states {
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_SCISSOR
- };
- ui_pipeline = api.create_graphics_pipeline("ui", (VkShaderStageFlagBits)(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), render_pass, dynamic_states);
-
- ImGui::CreateContext();
- auto io = ImGui::GetIO();
-
- uint8_t* pixels = nullptr;
- int atlas_width, atlas_height;
- io.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height);
-
- VkExtent3D atlas_size = {
- .width = (uint32_t)atlas_width,
- .height = (uint32_t)atlas_height,
- .depth = 1,
- };
staging_buffer = api.create_buffer(4096 * 4096 * 4 * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
- std::memcpy(staging_buffer.alloc_info.pMappedData, pixels, atlas_width * atlas_height * sizeof(uint32_t));
-
- // ui_texture = api.create_image(atlas_size, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- // io.Fonts->SetTexID((void*)&ui_texture);
-
- // VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index]))
-
- // Initialization frame
- // auto cmd_buf = command_buffers[virtual_frame_index];
- // api.start_record(cmd_buf);
-
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, ui_texture);
-
- // api.copy_buffer(cmd_buf, staging_buffer, ui_texture);
-
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, ui_texture);
-
- // api.end_record(cmd_buf);
-
-
- // api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]);
-
- // VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
-
- std::vector<image> images = {
- swapchain.images[0],
- swapchain.images[1],
- swapchain.images[2]
- };
-
- api.update_descriptor_images(images, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
-
- // std::vector<image> sampled_images = {
- // ui_texture
- // };
- // api.update_descriptor_images(sampled_images, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
-
- // ui_texture_sampler = api.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
-
- // std::vector<sampler> samplers = {
- // ui_texture_sampler,
- // };
- // api.update_descriptor_samplers(samplers);
-
- virtual_frame_index++;
-
- ui_vertex_buffers.resize(virtual_frames_count);
- ui_index_buffers.resize(virtual_frames_count);
}
vkrenderer::~vkrenderer() {
@@ -137,124 +54,23 @@ vkrenderer::~vkrenderer() {
api.destroy_semaphores(execution_semaphores);
api.destroy_semaphores(acquire_semaphores);
- api.destroy_render_pass(render_pass);
-
- // api.destroy_sampler(ui_texture_sampler);
-
- for (auto& framebuffer: framebuffers) {
- api.destroy_framebuffer(framebuffer);
- }
-
api.destroy_command_buffers(command_buffers);
api.destroy_pipeline(tonemapping_pipeline);
- api.destroy_pipeline(ui_pipeline);
api.destroy_swapchain(swapchain);
api.destroy_surface(platform_surface);
}
void vkrenderer::begin_frame() {
- ImGui::Render();
- // ImDrawData* draw_data = ImGui::GetDrawData();
-
VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index]))
- // if (ui_vertex_buffers[virtual_frame_index].size < draw_data->TotalVtxCount * sizeof(VkVertex)) {
- // api.destroy_buffer(ui_vertex_buffers[virtual_frame_index]);
-
- // ui_vertex_buffers[virtual_frame_index] = api.create_buffer(draw_data->TotalVtxCount * sizeof(VkVertex), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
- // }
- // if (ui_index_buffers[virtual_frame_index].size < draw_data->TotalIdxCount * sizeof(ImDrawIdx)) {
- // api.destroy_buffer(ui_index_buffers[virtual_frame_index]);
-
- // ui_index_buffers[virtual_frame_index] = api.create_buffer(draw_data->TotalIdxCount * sizeof(ImDrawIdx), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
- // }
-
- // off_t vertex_buffer_offset = 0;
- // off_t index_buffer_offset = 0;
- // for (uint32_t draw_list_index = 0; draw_list_index < draw_data->CmdListsCount; draw_list_index++) {
- // auto vertex_buffer = draw_data->CmdLists[draw_list_index]->VtxBuffer;
- // auto index_buffer = draw_data->CmdLists[draw_list_index]->IdxBuffer;
- // std::vector<VkVertex> vertices;
-
- // for (auto& imVertex: vertex_buffer) {
- // vertices.push_back(*((VkVertex*)&imVertex));
- // }
-
- // std::memcpy((void*) ((uint64_t)ui_vertex_buffers[virtual_frame_index].alloc_info.pMappedData + (vertex_buffer_offset * sizeof(VkVertex))), vertices.data(), vertex_buffer.Size * sizeof(VkVertex));
- // std::memcpy((void*) ((uint64_t)ui_index_buffers[virtual_frame_index].alloc_info.pMappedData + (index_buffer_offset * sizeof(ImDrawIdx))), index_buffer.Data, index_buffer.Size * sizeof(ImDrawIdx));
-
- // vertex_buffer_offset += vertex_buffer.Size;
- // index_buffer_offset += index_buffer.Size;
- // }
-
swapchain_image_index = 0;
auto acquire_result = vkAcquireNextImageKHR(api.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::ui() {
- ImDrawData* draw_data = ImGui::GetDrawData();
-
- auto cmd_buf = command_buffers[virtual_frame_index];
-
- api.begin_render_pass(cmd_buf, render_pass, framebuffers[swapchain_image_index], swapchain.extent, ui_pipeline);
-
- VkViewport viewport = {};
- viewport.x = draw_data->DisplayPos.x;
- viewport.y = draw_data->DisplayPos.y;
- viewport.width = draw_data->DisplaySize.x;
- viewport.height = draw_data->DisplaySize.y;
- viewport.minDepth = 0.f;
- viewport.maxDepth = 1.f;
-
- vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
-
- float scale[] {
- 2.f / draw_data->DisplaySize.x,
- 2.f / draw_data->DisplaySize.y,
- };
- float translate[] {
- -1.f - draw_data->DisplayPos.x * (2.f / draw_data->DisplaySize.x),
- -1.f - draw_data->DisplayPos.y * (2.f / draw_data->DisplaySize.y),
- };
- // vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 64, 8, (void*)&ui_vertex_buffers[virtual_frame_index].device_address);
- // vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 72, 8, (void*)&scale);
- // vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 80, 8, (void*)&translate);
-
- // vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 96, 4, (void*)&ui_texture.bindless_sampled_index);
- // vkCmdPushConstants(cmd_buf, api.bindless_descriptor.pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 100, 4, (void*)&ui_texture_sampler.bindless_index);
-
- off_t vertex_buffer_offset = 0;
- off_t index_buffer_offset = 0;
- for (size_t cmd_index = 0; cmd_index < draw_data->CmdListsCount; cmd_index++) {
- ImDrawList* draw_list = draw_data->CmdLists[cmd_index];
-
- for (auto& draw_cmd: draw_list->CmdBuffer) {
- VkRect2D rect = {};
- rect.offset = {
- (int32_t)draw_cmd.ClipRect.x,
- (int32_t)draw_cmd.ClipRect.y
- };
- rect.extent = {
- (uint32_t)draw_cmd.ClipRect.z,
- (uint32_t)draw_cmd.ClipRect.w,
- };
- vkCmdSetScissor(cmd_buf, 0, 1, &rect);
-
- api.draw(cmd_buf, ui_pipeline, ui_index_buffers[virtual_frame_index], draw_cmd.ElemCount, index_buffer_offset + draw_cmd.IdxOffset, vertex_buffer_offset + draw_cmd.VtxOffset);
- }
-
- vertex_buffer_offset += draw_list->VtxBuffer.Size;
- index_buffer_offset += draw_list->IdxBuffer.Size;
- }
-
- api.end_render_pass(cmd_buf);
}
void vkrenderer::compute(uint32_t width, uint32_t height) {
@@ -268,7 +84,7 @@ void vkrenderer::compute(uint32_t width, uint32_t height) {
void vkrenderer::finish_frame() {
auto cmd_buf = command_buffers[virtual_frame_index];
- // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_SHADER_WRITE_BIT, 0, swapchain.images[swapchain_image_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);
@@ -281,51 +97,23 @@ void vkrenderer::finish_frame() {
}
void vkrenderer::recreate_swapchain() {
- VKRESULT(vkWaitForFences(api.context.device, submission_fences.size(), submission_fences.data(), VK_TRUE, UINT64_MAX))
+ // VKRESULT(vkWaitForFences(api.context.device, submission_fences.size(), submission_fences.data(), VK_TRUE, UINT64_MAX))
+ auto swapchain_image_usages = api.get_image(swapchain.images[0]).usages;
struct swapchain old_swapchain = swapchain;
swapchain = api.create_swapchain(
platform_surface,
min_swapchain_image_count,
- VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
+ swapchain_image_usages,
old_swapchain.handle
);
api.destroy_swapchain(old_swapchain);
- VkExtent3D image_size = {
- .width = swapchain.extent.width,
- .height = swapchain.extent.height,
- .depth = 1,
- };
-
- auto cmd_buf = command_buffers[virtual_frame_index];
- api.start_record(cmd_buf);
-
- api.end_record(cmd_buf);
-
- VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[0]))
-
- api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[0]);
-
- VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[0], VK_TRUE, UINT64_MAX))
-
- std::vector<image> images = {
- swapchain.images[0],
- swapchain.images[1],
- swapchain.images[2]
- };
-
- api.update_descriptor_images(images, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
-
- for (auto& framebuffer: framebuffers) {
- api.destroy_framebuffer(framebuffer);
- }
- framebuffers.clear();
-
- for (auto& current_image : swapchain.images) {
- std::vector<image> attachments { current_image };
- framebuffers.push_back(api.create_framebuffer(render_pass, attachments, swapchain.extent));
+ swapchain_textures.resize(swapchain.image_count);
+ for (size_t index = 0; index < swapchain.image_count; index++) {
+ swapchain_textures[index] = new Texture();
+ swapchain_textures[index]->device_image = swapchain.images[index];
}
}
@@ -340,14 +128,17 @@ void vkrenderer::handle_swapchain_result(VkResult function_result) {
}
}
-void vkrenderer::update_image(Texture* texture, void* data, size_t size) {
- if (staging_buffer.size < size) {
+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(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
+ staging_buffer = api.create_buffer(max_texture_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
}
- std::memcpy(staging_buffer.alloc_info.pMappedData, data, size);
+ std::memcpy(buffer.alloc_info.pMappedData, data, max_texture_size);
VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index]))
@@ -359,7 +150,7 @@ void vkrenderer::update_image(Texture* texture, void* data, size_t size) {
api.copy_buffer(cmd_buf, staging_buffer, texture->device_image);
- api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 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);
@@ -367,9 +158,17 @@ void vkrenderer::update_image(Texture* texture, void* data, size_t size) {
api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]);
VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
+}
+void vkrenderer::update_buffer(Buffer* buffer, void* data, off_t offset, size_t size) {
+ auto device_buffer = api.get_buffer(buffer->device_buffer);
+
+ size_t dynamic_offset = buffer->isStatic ? 0 : buffer->size * virtual_frame_index;
+
+ std::memcpy((uint8_t*)device_buffer.alloc_info.pMappedData + dynamic_offset + offset, data, size);
}
+
Buffer* vkrenderer::create_buffer(size_t size, bool isStatic) {
auto buffer = new Buffer(this, size, isStatic);
@@ -378,6 +177,14 @@ Buffer* vkrenderer::create_buffer(size_t size, bool isStatic) {
return buffer;
}
+Buffer* vkrenderer::create_index_buffer(size_t size, bool isStatic) {
+ auto buffer = new Buffer(this, size, isStatic);
+
+ buffer->device_buffer = api.create_buffer(isStatic ? size : size * virtual_frames_count, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU);
+
+ return buffer;
+}
+
Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat format) {
auto texture = new Texture();
texture->device_image = api.create_image(
@@ -386,9 +193,6 @@ Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat for
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT
);
- api.update_descriptor_image(texture->device_image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- api.update_descriptor_image(texture->device_image, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
-
return texture;
}
@@ -398,8 +202,6 @@ Sampler* vkrenderer::create_sampler(VkFilter filter, VkSamplerAddressMode addres
sampler->device_sampler = api.create_sampler(filter, address_mode);
- api.update_descriptor_sampler(sampler->device_sampler);
-
return sampler;
}
@@ -409,22 +211,37 @@ ComputeRenderpass* vkrenderer::create_compute_renderpass() {
return (ComputeRenderpass*)renderpasses.back();
}
+PrimitiveRenderpass* vkrenderer::create_primitive_renderpass() {
+ renderpasses.push_back(new PrimitiveRenderpass(api));
+
+ return (PrimitiveRenderpass*)renderpasses.back();
+}
+
+Primitive* vkrenderer::create_primitive(PrimitiveRenderpass& primitive_render_pass) {
+ return new Primitive(api, primitive_render_pass);
+}
+
void vkrenderer::render() {
- begin_frame();
+ // begin_frame();
auto cmd_buf = command_buffers[virtual_frame_index];
- for (auto& renderpass: renderpasses) {
- renderpass->execute(cmd_buf);
+ // for (auto& renderpass: renderpasses) {
+ // renderpass->execute(*this, cmd_buf);
- api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, ((ComputeRenderpass*)renderpass)->output_texture->device_image);
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, ((ComputeRenderpass*)renderpass)->output_texture->device_image);
- api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, swapchain.images[swapchain_image_index]);
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, swapchain.images[swapchain_image_index]);
- api.blit_full(cmd_buf, ((ComputeRenderpass*)renderpass)->output_texture->device_image, swapchain.images[swapchain_image_index]);
+ // api.blit_full(cmd_buf, ((ComputeRenderpass*)renderpass)->output_texture->device_image, swapchain.images[swapchain_image_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]);
- }
- finish_frame();
+ // api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, swapchain.images[swapchain_image_index]);
+
+ renderpasses[1]->execute(*this, cmd_buf);
+
+ api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, swapchain.images[swapchain_image_index]);
+
+ // finish_frame();
}