aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2026-05-05 00:43:54 +0200
committerladevieq <ladevie.quentin@gmail.com>2026-05-05 00:49:12 +0200
commitc3aac9026951e2a6e35e76b9c7d36e114a281453 (patch)
treebdfc2ab5d5f1d196ba8c7a76371a29911f75913e
parent754249d9c652ef941e6b082d2e86538d15ba9434 (diff)
Remove old api and move api-test content to src and include dirs
-rw-r--r--api-test/main.cpp653
-rw-r--r--api-test/vk-bindless.cpp431
-rw-r--r--build.bat16
-rw-r--r--include/api-test/handle.hpp24
-rw-r--r--include/api-test/resource-manager.hpp22
-rw-r--r--include/api-test/texture.hpp17
-rw-r--r--include/api-test/vk-bindless.hpp93
-rw-r--r--include/buffer.hpp (renamed from include/api-test/buffer.hpp)0
-rw-r--r--include/bvh-node.hpp320
-rw-r--r--include/compute-renderpass.hpp41
-rw-r--r--include/dx12-command-buffer.hpp (renamed from include/api-test/dx12-command-buffer.hpp)0
-rw-r--r--include/dx12-device-types.hpp (renamed from include/api-test/dx12-device-types.hpp)0
-rw-r--r--include/dx12-device.hpp (renamed from include/api-test/dx12-device.hpp)0
-rw-r--r--include/freelist.hpp (renamed from include/api-test/freelist.hpp)39
-rw-r--r--include/handle.hpp13
-rw-r--r--include/primitive-renderpass.hpp93
-rw-r--r--include/renderpass.hpp22
-rw-r--r--include/texture.hpp86
-rw-r--r--include/vk-api.hpp219
-rw-r--r--include/vk-bindless.hpp49
-rw-r--r--include/vk-command-buffer.hpp (renamed from include/api-test/vk-command-buffer.hpp)30
-rw-r--r--include/vk-context.hpp49
-rw-r--r--include/vk-device-types.hpp (renamed from include/api-test/vk-device-types.hpp)57
-rw-r--r--include/vk-device.hpp (renamed from include/api-test/vk-device.hpp)30
-rw-r--r--include/vk-renderer.hpp164
-rw-r--r--include/vk-utils.hpp (renamed from include/api-test/vk-utils.hpp)6
-rw-r--r--src/compute-renderpass.cpp63
-rw-r--r--src/dx12-command-buffer.cpp (renamed from api-test/dx12-command-buffer.cpp)0
-rw-r--r--src/dx12-device.cpp (renamed from api-test/dx12-device.cpp)0
-rw-r--r--src/main.cpp1053
-rw-r--r--src/primitive-renderpass.cpp152
-rw-r--r--src/vk-api.cpp1257
-rw-r--r--src/vk-bindless.cpp238
-rw-r--r--src/vk-command-buffer.cpp (renamed from api-test/vk-command-buffer.cpp)75
-rw-r--r--src/vk-context.cpp319
-rw-r--r--src/vk-device.cpp (renamed from api-test/vk-device.cpp)127
-rw-r--r--src/vk-renderer.cpp284
-rw-r--r--src/vk-utils.cpp (renamed from api-test/vk-utils.cpp)2
38 files changed, 1215 insertions, 4829 deletions
diff --git a/api-test/main.cpp b/api-test/main.cpp
deleted file mode 100644
index f4a825d..0000000
--- a/api-test/main.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-// #include <cassert>
-// #include <cstdio>
-// #include <array>
-
-#define STB_IMAGE_IMPLEMENTATION
-// #include <stb_image.h>
-
-#include "imgui.cpp"
-#include "imgui_draw.cpp"
-#include "imgui_tables.cpp"
-#include "imgui_widgets.cpp"
-#include "imgui_demo.cpp"
-
-#define API_TEST
-
-#include "../src/vulkan-loader.cpp"
-#include "../src/window.cpp"
-#include "../src/vec3.cpp"
-#include "../src/camera.cpp"
-#include "../src/scene.cpp"
-#include "../src/utils.cpp"
-#include "../src/bvh.cpp"
-#include "../src/gltf.cpp"
-#include "../src/mesh.cpp"
-
-#include "vk-utils.cpp"
-#include "vk-device.cpp"
-#include "vk-bindless.cpp"
-#include "vk-command-buffer.cpp"
-
-// #include "handle.hpp"
-// #include "window.hpp"
-// #include "utils.hpp"
-
-#ifdef VK
-#include <vk_mem_alloc.h>
-#include "vk-device.hpp"
-#include "vk-command-buffer.hpp"
-#else
-#include "dx12-device.hpp"
-#include "dx12-command-buffer.hpp"
-#endif
-
-struct device_texture;
-
-#define VK
-// #define DX12
-
-#ifdef DEBUG
-#define ENABLE_RENDERDOC
-#endif // _DEBUG
-
-#include "camera.hpp"
-#include "scene.hpp"
-
-#ifdef ENABLE_RENDERDOC
-#include <renderdoc_app.h>
-
-#define RD_START_CAPTURE if(rdoc_api != nullptr) rdoc_api->StartFrameCapture(nullptr, nullptr)
-#define RD_END_CAPTURE if(rdoc_api != nullptr) rdoc_api->EndFrameCapture(nullptr, nullptr)
-
-RENDERDOC_API_1_6_0 *rdoc_api = nullptr;
-#else
-#define RD_START_CAPTURE (0)
-#define RD_END_CAPTURE (0)
-#endif // ENABLE_RENDERDOC
-
-static constexpr size_t Kb = 1024U;
-static constexpr size_t Mb = 1024U * Kb;
-
-static uintptr_t transmittance_LUT_tex_id = 0U;
-
-void ui(uint64_t frame_time) {
- static float max_fps = 0.f;
- static uint64_t max_frame_time = 1000U;
- float fps = static_cast<float>(1000000U / frame_time);
- if (fps > max_fps) {
- max_fps = fps;
- }
- if (frame_time > max_frame_time) {
- max_frame_time = frame_time;
- }
- ImGui::NewFrame();
- ImGui::Text("FPS : %f\n", fps);
- ImGui::Text("Max FPS : %f\n", max_fps);
- ImGui::Text("frame_time : %f ms\n", frame_time / 1000.f);
- ImGui::Text("max frame_time : %f ms\n", max_frame_time / 1000.f);
-
- ImGui::Text("LUT");
- ImGui::Image(transmittance_LUT_tex_id, ImVec2(128, 128));
- ImGui::EndFrame();
- ImGui::Render();
-}
-
-void update_buffers(ImDrawData* draw_data, const device_buffer& vertex_buffer, const device_buffer& index_buffer) {
- off_t vertex_offset = 0;
- off_t index_offset = 0;
- for (auto index {0} ; index < draw_data->CmdListsCount; index++) {
- auto* cmd_list = draw_data->CmdLists[index];
-
- size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size();
- auto* vtx_ptr = static_cast<uint8_t*>(vertex_buffer.mapped_ptr) + vertex_offset;
- memcpy(vtx_ptr, cmd_list->VtxBuffer.Data, vertex_bytes_size);
- vertex_offset += static_cast<off_t>(vertex_bytes_size);
-
- size_t index_bytes_size = sizeof(ImDrawIdx) * cmd_list->IdxBuffer.size();
- memcpy(static_cast<uint8_t*>(index_buffer.mapped_ptr) + index_offset, cmd_list->IdxBuffer.Data, index_bytes_size);
- index_offset += static_cast<off_t>(index_bytes_size);
- }
-}
-
-int main() {
- LARGE_INTEGER freq;
- // From Microsoft doc
- // https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancefrequency
- // The frequency of the performance counter is fixed at system boot and is
- // consistent across all processors so you only need to query the frequency
- // from QueryPerformanceFrequency as the application initializes,
- // and then cache the result.
- QueryPerformanceFrequency(&freq);
-
-#ifdef ENABLE_RENDERDOC
- {
- HMODULE mod = GetModuleHandleA("renderdoc.dll");
- // if (!mod) {
- // mod = LoadLibraryA("renderdoc.dll");
- // }
-
- if (mod) {
- auto RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
- assert(RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void **)&rdoc_api) == 1);
- }
-
- // if (!rdoc_api->IsTargetControlConnected()) {
- // rdoc_api->LaunchReplayUI(true, nullptr);
- // }
- }
-#endif
-
- constexpr size_t window_width = 1280U;
- constexpr size_t window_height = 720U;
- window wnd { window_width, window_height };
-
- ImGui::CreateContext();
- ImGuiIO &io = ImGui::GetIO();
- io.DisplaySize.x = window_width;
- io.DisplaySize.y = window_height;
-
- const float aspect_ratio = 16.f / 9.f;
-
- point3 position { 13.f, 2.f, -3.f };
- point3 target {};
- const auto v_fov = 90.f;
- const auto aperture = 0.1f;
- const auto focus_distance = 10.f;
-
-#ifdef VK
- auto& device = vkdevice::get_render_device();
-#else
- auto& device = dx12::device::get_render_device();
-#endif
- device.init();
-
-#ifdef VK
- auto main_scene = scene(camera(position, target, v_fov, aspect_ratio, aperture, focus_distance), window_width, window_height);
-#endif
-
- auto surface_handle = device.create_surface({
- .window_handle = wnd.handle,
-#ifdef VK
- .surface_format = {
- .format = VK_FORMAT_B8G8R8A8_UNORM,
- .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
- },
- .present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR,
- .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
-#else
- .surface_format = DXGI_FORMAT_R16G16B16A16_FLOAT,
- .present_mode = DXGI_SWAP_EFFECT_FLIP_DISCARD,
- .usages = DXGI_USAGE_RENDER_TARGET_OUTPUT,
-#endif
- .image_count = 2U,
- });
- auto& surface = device.get_surface(surface_handle);
-
- constexpr size_t image_size = 1024U;
- constexpr size_t image_count = 4U;
- auto staging_buffer_handle = device.create_buffer({
- .size = image_size * image_size * sizeof(uint32_t) * image_count,
-#ifdef VK
- .usages = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
-#else
-
- .map = true,
- .states = D3D12_RESOURCE_STATE_COPY_SOURCE,
- .usages = D3D12_RESOURCE_FLAG_NONE,
- .heap_type = D3D12_HEAP_TYPE_UPLOAD,
-#endif
- });
- const auto& staging_buffer = device.get_buffer(staging_buffer_handle);
-
- // API test code
- int width;
- int height;
- int channels;
- uint8_t* data = stbi_load("../models/sponza/466164707995436622.jpg", &width, &height, &channels, 4);
- size_t size = static_cast<size_t>(width) * height * 4U;
- memcpy(staging_buffer.mapped_ptr, data, size);
-
- auto gpu_texture_handle = device.create_texture({
- .width = static_cast<uint32_t>(width),
- .height = static_cast<uint32_t>(height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
- .format = VK_FORMAT_R8G8B8A8_UNORM,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .states = D3D12_RESOURCE_STATE_COPY_DEST,
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
-
- off_t buffer_offset = width * height * 4;
- data = stbi_load("../models/sponza/715093869573992647.jpg", &width, &height, &channels, 4);
- size = static_cast<size_t>(width) * height * 4U;
- auto* addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + buffer_offset);
- memcpy(addr, data, size);
-
- auto second_texture = device.create_texture({
- .width = static_cast<uint32_t>(width),
- .height = static_cast<uint32_t>(height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
- .format = VK_FORMAT_R8G8B8A8_UNORM,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .states = D3D12_RESOURCE_STATE_COPY_DEST,
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
-
- auto output_texture_handle = device.create_texture({
- .width = static_cast<uint32_t>(width),
- .height = static_cast<uint32_t>(height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_STORAGE_BIT,
- .format = VK_FORMAT_R8G8B8A8_UNORM,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
-
- uint8_t *pixels = nullptr;
- int atlas_width;
- int atlas_height;
- io.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height);
- const auto ui_texture_handle = device.create_texture({
- .width = static_cast<uint32_t>(atlas_width),
- .height = static_cast<uint32_t>(atlas_height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
- .format = VK_FORMAT_R8G8B8A8_UNORM,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .states = D3D12_RESOURCE_STATE_COPY_DEST,
- .usages = D3D12_RESOURCE_FLAG_NONE,
- .format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
- const auto& ui_texture = device.get_texture(ui_texture_handle);
- // io.Fonts->SetTexID(*(void **)&ui_texture_handle.id);
- io.Fonts->SetTexID(reinterpret_cast<void*>(ui_texture.get_sampled_index()));
-
- off_t ui_offset = 2L * buffer_offset;
- size = static_cast<size_t>(atlas_width) * atlas_height * 4U;
- addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + ui_offset);
- memcpy(addr, pixels, size);
-
- auto vertex_buffer_handle = device.create_buffer({
- .size = Mb * sizeof(uint32_t),
-#ifdef VK
- .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
-#else
- #endif
- });
- auto vertex_buffer = device.get_buffer(vertex_buffer_handle);
-
- auto index_buffer_handle = device.create_buffer({
- .size = Mb * sizeof(uint32_t),
-#ifdef VK
- .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
-#else
-#endif
- });
- auto index_buffer = device.get_buffer(index_buffer_handle);
-
-#ifdef VK
- auto code = read_file("shaders/test.comp.spv");
- auto compute = device.create_compute_pipeline({
- .cs_code = code,
- });
-
- auto rt_code = read_file("shaders/compute.comp.spv");
- auto raytracing = device.create_compute_pipeline({
- .cs_code = rt_code,
- });
- auto tonemapping_code = read_file("shaders/tonemapping.comp.spv");
- auto tonemapping = device.create_compute_pipeline({
- .cs_code = tonemapping_code,
- });
-#endif
- const auto acc_handle = device.create_texture({
- .width = static_cast<uint32_t>(window_width),
- .height = static_cast<uint32_t>(window_height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
- .format = VK_FORMAT_R32G32B32A32_SFLOAT,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R32G32B32A32_FLOAT,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
-
-#ifdef VK
- auto acc_storage_index = device.get_texture(acc_handle).get_storage_index();
-#endif
-
- const auto result_handle = device.create_texture({
- .width = static_cast<uint32_t>(window_width),
- .height = static_cast<uint32_t>(window_height),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
- .format = VK_FORMAT_R32G32B32A32_SFLOAT,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R32G32B32A32_FLOAT,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- });
-#ifdef VK
- auto result_storage_index = device.get_texture(result_handle).get_storage_index();
-#endif
-
-#ifdef VK
- std::array<VkFormat, 1U> formats { surface.surface_format.format };
- auto vertex_code = read_file("shaders/api-test-ui.vert.spv");
- auto fragment_code = read_file("shaders/api-test-ui.frag.spv");
- auto graphics = device.create_graphics_pipeline({
- .vs_code = vertex_code,
- .fs_code = fragment_code,
- .color_attachments_format = formats
- });
-#endif
-
-#ifdef VK
- std::array<graphics_command_buffer, 4U> graphics_command_buffers;
- device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), QueueType::GRAPHICS, "graphics_cmd_buf");
-#else
- std::array<dx12::graphics_command_buffer, 4U> graphics_command_buffers;
- device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), dx12::QueueType::GRAPHICS);
-#endif
-
-
- handle<device_texture> transmittance_lut_handle = device.create_texture({
- .width = static_cast<uint32_t>(1024),
- .height = static_cast<uint32_t>(1024),
-#ifdef VK
- .usages = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
- .format = VK_FORMAT_R16G16B16A16_SFLOAT,
- .type = VK_IMAGE_TYPE_2D,
-#else
- .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
- .format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
-#endif
- .name = "transmittance_lut",
- });
- device_texture transmittance_lut = device.get_texture(transmittance_lut_handle);
- transmittance_LUT_tex_id = transmittance_lut.get_sampled_index();
-
- std::vector<uint8_t> transmittance_lut_code = read_file("shaders/transmittance_lut.comp.spv");
- handle<device_pipeline> transmittance_lut_compute = device.create_compute_pipeline({
- .cs_code = transmittance_lut_code,
- .name = "transmittance_lut_comp",
- });
-
-
- // API test code
- RD_START_CAPTURE;
-
- graphics_command_buffers[0].start();
-
-#ifdef VK
- graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- graphics_command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
-#endif
-
- graphics_command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle);
- graphics_command_buffers[0].copy(staging_buffer_handle, second_texture, buffer_offset);
- graphics_command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, ui_offset);
-#ifdef VK
- graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
-
- {
- graphics_command_buffers[0].dispatch({
- .pipeline = compute,
- .group_size = { .vec = { image_size, image_size, 1U }},
- .local_group_size = { .vec = { 8U, 8U, 1U }},
- .params = {
- device.get_texture(second_texture).get_storage_index(), // Input 1
- device.get_texture(gpu_texture_handle).get_storage_index(), // Input 2
- device.get_texture(output_texture_handle).get_storage_index(), // Output
- },
- });
-
- graphics_command_buffers[0].dispatch({
- .pipeline = transmittance_lut_compute,
- .group_size = { .vec = { 1024U, 1024U, 1U }},
- .local_group_size = { .vec { 8U, 8U, 1U }},
- .params = {
- transmittance_lut.get_storage_index(),
- uint64_t(transmittance_lut.width) << 32U | transmittance_lut.height,
- }
- });
- }
-
- graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-#endif
-
- graphics_command_buffers[0].stop();
-
- device.submit(graphics_command_buffers.data(), 1);
- device.wait();
-
- RD_END_CAPTURE;
-
- // watcher::watch_file(std::filesystem::path("../shaders/compute.comp"), [&]() {
- // printf("change");
- // });
-
-#ifdef VK
- std::array<handle<device_texture>, 1U> color_attachment {};
- constexpr uint32_t virtual_frames_count = 2U;
- uint64_t frame_time = 1U;
- uint32_t frame_count = 0U;
- while(wnd.isOpen) {
- LARGE_INTEGER start_qpc;
- QueryPerformanceCounter(&start_qpc);
- wnd.poll_events();
-
- watcher::pull_changes();
-
- uint32_t virtual_frame_index = frame_count % virtual_frames_count;
- auto command_buffer = graphics_command_buffers[2U + virtual_frame_index];
- for (auto& event : wnd.events) {
- if (event.type == EVENT_TYPES::MOUSE_MOVE) {
- io.MousePos.x = static_cast<float>(event.data.position.x);
- io.MousePos.y = static_cast<float>(event.data.position.y);
- }
-
- io.MouseDown[0] = event.type == EVENT_TYPES::BUTTON_PRESS;
- }
-
- ui(frame_time);
-
- auto* draw_data = ImGui::GetDrawData();
- update_buffers(draw_data, vertex_buffer, index_buffer);
-
- const auto& scene_buffer = device.get_buffer(main_scene.scene_buffer_handle);
- main_scene.meta.sample_index = frame_count;
- uint8_t* ptr = static_cast<uint8_t*>(scene_buffer.mapped_ptr);
- memcpy(static_cast<void*>(ptr), &main_scene.meta, sizeof(main_scene.meta));
- memcpy(static_cast<void*>(ptr + sizeof(main_scene.meta)), &main_scene.meta, sizeof(main_scene.meta));
- memcpy(static_cast<void*>(ptr + sizeof(main_scene.meta) * 2U), &main_scene.meta, sizeof(main_scene.meta));
-
- // TODO: Refactor backbuffer acquisition
- auto backbuffer = surface.swapchain_images[device.acquire_image_index(surface_handle)];
- color_attachment[0] = backbuffer;
-
- // RD_START_CAPTURE;
- command_buffer.start();
-
- command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
-
- {
- uint64_t textures = (virtual_frame_index == 0U) ? ((uint64_t(acc_storage_index) << 32U) | result_storage_index) : ((uint64_t(result_storage_index) << 32U) | acc_storage_index);
-
- if (virtual_frame_index == 0) {
- command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
- command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL);
- } else {
- command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL);
- command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
- }
-
- command_buffer.dispatch({
- .pipeline = raytracing,
- .group_size = { .vec { window_width, window_height, 1U, } },
- .local_group_size = { .vec { 8U, 8U, 1U, } },
- .params = {
- main_scene.scene_buffer_address(),
- main_scene.bvh_buffer_address(),
- main_scene.indices_buffer_address(),
- main_scene.positions_buffer_address(),
- main_scene.normals_buffer_address(),
- main_scene.uvs_buffer_address(),
- main_scene.materials_buffer_address(),
- textures,
- },
- });
-
- // TODO: Refactor backbuffer acquisition
- auto backbuffer_storage_index = device.get_texture(backbuffer).get_storage_index();
- uint64_t out = (virtual_frame_index == 0U) ? ((uint64_t(result_storage_index) << 32U) | backbuffer_storage_index) : ((uint64_t(acc_storage_index) << 32U) | backbuffer_storage_index);
- command_buffer.dispatch({
- .pipeline = tonemapping,
- .group_size = { .vec { window_width, window_height, 1U, } },
- .local_group_size = { .vec { 8U, 8U, 1U, } },
- .params = {
- main_scene.scene_buffer_address(),
- main_scene.bvh_buffer_address(),
- main_scene.indices_buffer_address(),
- main_scene.positions_buffer_address(),
- main_scene.normals_buffer_address(),
- main_scene.uvs_buffer_address(),
- main_scene.materials_buffer_address(),
- out,
- },
- });
- }
-
- command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
-
- command_buffer.begin_renderpass({
- .render_area = {
- .x = static_cast<int32_t>(draw_data->DisplayPos.x),
- .y = static_cast<int32_t>(draw_data->DisplayPos.y),
- .width = static_cast<uint32_t>(draw_data->DisplaySize.x),
- .height = static_cast<uint32_t>(draw_data->DisplaySize.y),
- },
- .color_attachments = color_attachment,
- });
-
- auto& draws_uniform_buffer = device.get_bindingmodel().get_draws_uniform_buffer();
- uint32_t vertex_offset = 0;
- uint32_t index_offset = 0;
- for (auto index {0} ; index < draw_data->CmdListsCount; index++) {
- auto* cmd_list = draw_data->CmdLists[index];
-
- for (auto& draw_command : cmd_list->CmdBuffer) {
- auto offset = draws_uniform_buffer.offset;
- ImTextureID texture_id = draw_command.TexRef.GetTexID();
- {
- struct ui_params {
- // uintptr_t vertex_buffer;
- float scale[2U];
- float translate[2U];
- uint32_t texture_index;
- };
- auto* ui_param = draws_uniform_buffer.allocate<ui_params>();
- *ui_param = ui_params{
- // .vertex_buffer = vertex_buffer.device_address,
- .scale {
- 2.f / draw_data->DisplaySize.x,
- 2.f / draw_data->DisplaySize.y,
- },
- .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),
- },
- .texture_index = *reinterpret_cast<uint32_t*>(&texture_id),
- };
- }
-
- command_buffer.draw_indexed({
- .pipeline = graphics,
- .index_buffer = index_buffer_handle,
- .vertex_count = draw_command.ElemCount,
- .vertex_offset = draw_command.VtxOffset + vertex_offset,
- .index_offset = draw_command.IdxOffset + index_offset,
- .instance_count = 1U,
- .uniforms_address = draws_uniform_buffer.device_address + offset,
- .vertex_address = vertex_buffer.device_address,
- });
- }
- vertex_offset += cmd_list->VtxBuffer.size();
- index_offset += cmd_list->IdxBuffer.size();
- }
-
- command_buffer.end_renderpass();
- command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
-
- command_buffer.stop();
-
- device.submit_before_present(surface_handle, &command_buffer, 1U);
- device.present(surface_handle);
- device.wait();
-
- LARGE_INTEGER end_qpc;
- QueryPerformanceCounter(&end_qpc);
- LONGLONG diff_qpc = end_qpc.QuadPart - start_qpc.QuadPart;
- frame_time = (diff_qpc * 1000000ULL) / freq.QuadPart;
- frame_count++;
-
- // RD_END_CAPTURE;
- }
-
- device.wait();
- device.destroy_surface(surface_handle);
-
- device.destroy_pipeline(compute);
- device.destroy_pipeline(graphics);
- device.destroy_pipeline(raytracing);
- device.destroy_pipeline(tonemapping);
-
- device.destroy_texture(gpu_texture_handle);
- device.destroy_texture(second_texture);
- device.destroy_texture(output_texture_handle);
- device.destroy_texture(ui_texture_handle);
- device.destroy_texture(acc_handle);
- device.destroy_texture(result_handle);
-
- device.destroy_buffer(staging_buffer_handle);
- device.destroy_buffer(vertex_buffer_handle);
- device.destroy_buffer(index_buffer_handle);
- device.deinit();
-
- ImGui::DestroyContext();
-#endif // VK
-
- return 0;
-}
diff --git a/api-test/vk-bindless.cpp b/api-test/vk-bindless.cpp
deleted file mode 100644
index d3d6415..0000000
--- a/api-test/vk-bindless.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-#include "vk-bindless.hpp"
-
-#include <vk_mem_alloc.h>
-#include <vulkan/vulkan_core.h>
-
-#include "vk-device.hpp"
-#include "vk-utils.hpp"
-#include "vulkan-loader.hpp"
-
-device_buffer& bindless_model::get_globals_uniform_buffer() const {
- auto& render_device = vkdevice::get_render_device();
- return render_device.get_buffer(globals_uniform_buffer_handle);
-}
-
-device_buffer& bindless_model::get_draws_uniform_buffer() const {
- auto& render_device = vkdevice::get_render_device();
- return render_device.get_buffer(draws_uniform_buffer_handle);
-}
-
-bindless_model bindless_model::create_bindless_model() {
- bindless_model bindless;
- auto& render_device = vkdevice::get_render_device();
- auto* device = render_device.get_device();
-#ifndef USE_VK_DESCRIPTOR_BUFFER
- bindless.create_immutable_samplers(device);
- bindless.create_layout(device);
- bindless.create_descriptor_pool(device);
- bindless.allocate_sets(device);
-
- // VkWriteDescriptorSet writes_descriptor_set[BindlessSetType::MAX];
-
- // {
- bindless.globals_uniform_buffer_handle = render_device.create_buffer({
- .size = globals_uniform_buffer_size,
- .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- });
-
- // const auto& buffer = render_device.get_buffer(bindless.globals_uniform_buffer_handle);
- // VkDescriptorBufferInfo buffer_info {
- // .buffer = buffer.vk_buffer,
- // .offset = 0U,
- // .range = VK_WHOLE_SIZE,
- // };
-
- // writes_descriptor_set[BindlessSetType::GLOBAL] = {
- // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- // .pNext = nullptr,
- // .dstSet = bindless.sets[BindlessSetType::GLOBAL],
- // .dstBinding = 3U,
- // .dstArrayElement = 0U,
- // .descriptorCount = 1U,
- // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- // .pImageInfo = nullptr,
- // .pBufferInfo = &buffer_info,
- // .pTexelBufferView = nullptr,
- // };
- // }
-
- // {
- // bindless.instances_uniform_buffer_handle = render_device.create_buffer({
- // .size = instances_uniform_buffer_size,
- // .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
- // .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- // .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- // });
-
- // const auto& buffer = render_device.get_buffer(bindless.instances_uniform_buffer_handle);
- // VkDescriptorBufferInfo buffer_info {
- // .buffer = buffer.vk_buffer,
- // .offset = 0U,
- // .range = VK_WHOLE_SIZE,
- // };
-
- // writes_descriptor_set[BindlessSetType::INSTANCES_UNIFORMS] = {
- // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- // .pNext = nullptr,
- // .dstSet = bindless.sets[BindlessSetType::INSTANCES_UNIFORMS],
- // .dstBinding = 0U,
- // .dstArrayElement = 0U,
- // .descriptorCount = 1U,
- // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- // .pImageInfo = nullptr,
- // .pBufferInfo = &buffer_info,
- // .pTexelBufferView = nullptr,
- // };
- // }
-
- // {
- bindless.draws_uniform_buffer_handle = render_device.create_buffer({
- .size = draws_uniform_buffer_size,
- .usages = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- });
-
- // const auto& buffer = render_device.get_buffer(bindless.draws_uniform_buffer_handle);
- // VkDescriptorBufferInfo buffer_info {
- // .buffer = buffer.vk_buffer,
- // .offset = 0U,
- // .range = draws_uniform_buffer_size,
- // };
-
- // writes_descriptor_set[BindlessSetType::DRAWS_UNIFORMS] = {
- // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- // .pNext = nullptr,
- // .dstSet = bindless.sets[BindlessSetType::DRAWS_UNIFORMS],
- // .dstBinding = 0U,
- // .dstArrayElement = 0U,
- // .descriptorCount = 1U,
- // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- // .pImageInfo = nullptr,
- // .pBufferInfo = &buffer_info,
- // .pTexelBufferView = nullptr,
- // };
- // }
-
- // vkUpdateDescriptorSets(device, sizeof(writes_descriptor_set) / sizeof(VkWriteDescriptorSet), writes_descriptor_set, 0U, nullptr);
-#else
- VkBufferCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .size = desc.size,
- .usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT,
- .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
- .queueFamilyIndexCount = 0,
- .pQueueFamilyIndices = nullptr,
- };
-
- VmaAllocatorCreateFlags alloc_create_flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
- VmaAllocationCreateInfo alloc_create_info{
- .flags = alloc_create_flags,
- .usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- .requiredFlags = desc.memory_properties,
- .preferredFlags = 0U,
- .memoryTypeBits = 0U,
- .pool = nullptr,
- .pUserData = nullptr,
- };
-
- VmaAllocationInfo alloc_info{};
-
- VKCHECK(vmaCreateBuffer(gpu_allocator, &create_info, &alloc_create_info, &device_buffer.vk_buffer, &device_buffer.alloc, &alloc_info));
-
- device_buffer.mapped_ptr = alloc_info.pMappedData;
-
- return { buffers.add(device_buffer) };
-#endif
-
- return bindless;
-}
-
-void bindless_model::destroy_bindless_model(bindless_model& bindless) {
- auto& render_device = vkdevice::get_render_device();
- auto* device = vkdevice::get_render_device().get_device();
- vkDestroyDescriptorPool(device, bindless.descriptor_pool, nullptr);
-
- for (auto index{ 0U }; index < BindlessSetType::MAX; index++) {
- vkDestroyDescriptorSetLayout(device, bindless.sets_layout[index], nullptr);
- }
-
- vkDestroyPipelineLayout(device, bindless.graphics_layout, nullptr);
- vkDestroyPipelineLayout(device, bindless.compute_layout, nullptr);
-
- bindless.destroy_immutable_samplers(device);
-
- // render_device.destroy_buffer(bindless.instances_uniform_buffer_handle);
- render_device.destroy_buffer(bindless.draws_uniform_buffer_handle);
-}
-
-void bindless_model::create_layout(VkDevice device) {
- // Set 0 global resources
- // Binding 0 Storage images
- // Binding 1 Sampled images
- // Binding 2 Samplers
- // Binding 3 Dynamic Uniform Buffer
- {
- VkDescriptorSetLayoutBinding set_layout_bindings[]{
- {
- .binding = 0U,
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
- .descriptorCount = SamplerType::MAX_SAMPLER,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = samplers,
- },
- {
- .binding = 1U,
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .descriptorCount = set_descriptors_count,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = nullptr,
- },
- {
- .binding = 2U,
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
- .descriptorCount = set_descriptors_count,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = nullptr,
- },
- // {
- // .binding = 3U,
- // .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- // .descriptorCount = 1U,
- // .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- // .pImmutableSamplers = nullptr,
- // },
- };
-
- VkDescriptorBindingFlags flags[]{
- VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
- VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
- VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
- // VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
- // 0U,
- };
-
- VkDescriptorSetLayoutBindingFlagsCreateInfo layout_binding_flags{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
- .pNext = VK_NULL_HANDLE,
- .bindingCount = sizeof(flags) / sizeof(VkDescriptorBindingFlags),
- .pBindingFlags = flags,
- };
-
- VkDescriptorSetLayoutCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = &layout_binding_flags,
- .flags = 0U,
- .bindingCount = sizeof(set_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding),
- .pBindings = set_layout_bindings,
- };
-
- VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::GLOBAL]));
- }
-
- // Set 1 per instance uniforms
- // Binding 0 Dynamic Uniform Buffer
- {
- VkDescriptorSetLayoutBinding set_layout_bindings[]{
- {
- .binding = 0U,
- .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- .descriptorCount = 1U,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = nullptr,
- },
- };
-
- VkDescriptorSetLayoutCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .bindingCount = sizeof(set_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding),
- .pBindings = set_layout_bindings,
- };
-
- VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::INSTANCES_UNIFORMS]));
- }
-
- // Set 2 per draw uniforms
- // Binding 0 Dynamic Uniform Buffer
- {
- VkDescriptorSetLayoutBinding set_layout_bindings[]{
- {
- .binding = 0U,
- .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- .descriptorCount = 1,
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .pImmutableSamplers = nullptr,
- },
- };
-
- VkDescriptorSetLayoutCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .bindingCount = sizeof(set_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding),
- .pBindings = set_layout_bindings,
- };
-
- VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &sets_layout[BindlessSetType::DRAWS_UNIFORMS]));
- }
-
- {
- VkPushConstantRange push_constants[] {
- {
- .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
- .offset = 0U,
- .size = max_push_constants_slots_size * (max_push_constants_slots),
- },
- };
-
- VkPipelineLayoutCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .setLayoutCount = sizeof(sets_layout) / sizeof(VkDescriptorSetLayout),
- .pSetLayouts = sets_layout,
- .pushConstantRangeCount = sizeof(push_constants) / sizeof(push_constants[0]),
- .pPushConstantRanges = push_constants,
- };
-
- VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &graphics_layout));
- }
-
- {
- VkPushConstantRange push_constants[] {
- {
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
- .offset = 0U,
- .size = max_push_constants_slots_size * max_push_constants_slots,
- },
- };
-
-
- VkPipelineLayoutCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .setLayoutCount = sizeof(sets_layout) / sizeof(VkDescriptorSetLayout),
- .pSetLayouts = sets_layout,
- .pushConstantRangeCount = sizeof(push_constants) / sizeof(push_constants[0]),
- .pPushConstantRanges = push_constants,
- };
-
- VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &compute_layout));
- }
-}
-
-#ifndef USE_VK_DESCRIPTOR_BUFFER
-void bindless_model::create_descriptor_pool(VkDevice device) {
- VkDescriptorPoolSize pool_sizes[]{
- {
- .type = VK_DESCRIPTOR_TYPE_SAMPLER,
- .descriptorCount = set_descriptors_count,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .descriptorCount = set_descriptors_count,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
- .descriptorCount = set_descriptors_count,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
- .descriptorCount = 8U,
- },
- };
-
- VkDescriptorPoolCreateInfo descriptor_pool_create_info{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .maxSets = descriptor_pool_allocable_sets_count,
- .poolSizeCount = sizeof(pool_sizes) / sizeof(VkDescriptorPoolSize),
- .pPoolSizes = pool_sizes,
- };
- VKCHECK(vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool));
-}
-
-void bindless_model::allocate_sets(VkDevice device) {
- VkDescriptorSetAllocateInfo allocate_info{
- .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
- .pNext = nullptr,
- .descriptorPool = descriptor_pool,
- .descriptorSetCount = 1U,
- .pSetLayouts = &sets_layout[BindlessSetType::GLOBAL],
- };
- VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::GLOBAL]));
-
- allocate_info.pSetLayouts = &sets_layout[BindlessSetType::INSTANCES_UNIFORMS],
- VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::INSTANCES_UNIFORMS]));
-
- allocate_info.pSetLayouts = &sets_layout[BindlessSetType::DRAWS_UNIFORMS],
- VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &sets[BindlessSetType::DRAWS_UNIFORMS]));
-}
-
-void bindless_model::create_immutable_samplers(VkDevice device) {
- VkSamplerCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
- .pNext = VK_NULL_HANDLE,
- .flags = 0,
- .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
- .mipLodBias = 0.f,
- .anisotropyEnable = VK_FALSE,
- .compareEnable = VK_FALSE,
- .compareOp = VK_COMPARE_OP_NEVER,
- .minLod = 0.f,
- .maxLod = 0.f,
- .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
- .unnormalizedCoordinates = VK_FALSE,
- };
-
- // Nearest sampler creation
- {
- VkFilter filter = VK_FILTER_NEAREST;
- VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-
- create_info.magFilter = filter,
- create_info.minFilter = filter,
- create_info.addressModeU = address_mode,
- create_info.addressModeV = address_mode,
- create_info.addressModeW = address_mode,
-
- VKCHECK(vkCreateSampler(device, &create_info, VK_NULL_HANDLE, &samplers[SamplerType::NEAREST]));
- }
-
- // Linear sampler creation
- {
- VkFilter filter = VK_FILTER_LINEAR;
- VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-
- create_info.magFilter = filter,
- create_info.minFilter = filter,
- create_info.addressModeU = address_mode,
- create_info.addressModeV = address_mode,
- create_info.addressModeW = address_mode,
-
- VKCHECK(vkCreateSampler(device, &create_info, VK_NULL_HANDLE, &samplers[SamplerType::LINEAR]));
- }
-}
-
-void bindless_model::destroy_immutable_samplers(VkDevice device) {
- for (auto* sampler : samplers) {
- vkDestroySampler(device, sampler, nullptr);
- }
-}
-#else
-#endif
diff --git a/build.bat b/build.bat
index c2c9018..674eaf3 100644
--- a/build.bat
+++ b/build.bat
@@ -41,13 +41,13 @@ set DEBUG_L_FLAGS=
set RELEASE_C_FLAGS=
if %MSVC% EQU 1 (
- set C_FLAGS=/nologo /W4 /WX /Zi /Fo:%BUILD_DIR%\ /Iinclude /Iinclude\api-test /I%VULKAN_SDK%\Include /external:W0 /external:Ithirdparty /external:Ithirdparty\imgui /std:c++20 /DNOMINMAX /EHsc /c /Tp
+ set C_FLAGS=/nologo /W4 /WX /Zi /Fo:%BUILD_DIR%\ /Iinclude /I%VULKAN_SDK%\Include /external:W0 /external:Ithirdparty /external:Ithirdparty\imgui /std:c++20 /DNOMINMAX /EHsc /c /Tp
set DEBUG_C_FLAGS=/DDEBUG /Od
set RELEASE_C_FLAGS=/DNDEBUG /O2
set DEBUG_L_FLAGS=/DEBUG
) else (
- set C_FLAGS=--target=x86_64-pc-windows-msvc -pedantic -I include -I include\api-test -I %VULKAN_SDK%\Include -isystem thirdparty -isystem thirdparty\imgui -std=c++20 -DNOMINMAX -c -msse4.1 -Wno-missing-designated-field-initializers
+ set C_FLAGS=--target=x86_64-pc-windows-msvc -pedantic -I include -I %VULKAN_SDK%\Include -isystem thirdparty -isystem thirdparty\imgui -std=c++20 -DNOMINMAX -c -msse4.1 -Wno-missing-designated-field-initializers
set DEBUG_C_FLAGS=-DDEBUG -g -O0
set RELEASE_C_FLAGS=-DNDEBUG -O2
@@ -76,19 +76,19 @@ if 0 EQU 1 (
:: set src=main dx12-device dx12-command-buffer
:: (for %%s in (%api%) do (
:: call set OBJS=%%OBJS%% %BUILD_DIR%\%%s.obj
-:: echo %C_COMPILER% /Fd:%BUILD_DIR%\%%s.pdb %C_FLAGS% api-test\%%s.cpp
-:: %C_COMPILER% /Fd:%BUILD_DIR%\%%s.pdb %C_FLAGS% api-test\%%s.cpp
+:: echo %C_COMPILER% /Fd:%BUILD_DIR%\%%s.pdb %C_FLAGS% src\%%s.cpp
+:: %C_COMPILER% /Fd:%BUILD_DIR%\%%s.pdb %C_FLAGS% src\%%s.cpp
:: ))
:: link multiple objs
:: link %L_FLAGS% /OUT:%BUILD_DIR%\main.exe %OBJS% kernel32.lib user32.lib
:: compiles the project as a single compilation unit
if %MSVC% EQU 1 (
- echo %C_COMPILER% /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% api-test\main.cpp
- %C_COMPILER% /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% api-test\main.cpp
+ echo %C_COMPILER% /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% src\main.cpp
+ %C_COMPILER% /Fd:%BUILD_DIR%\main.pdb %C_FLAGS% src\main.cpp
) else (
- echo %C_COMPILER% -o %BUILD_DIR%\main.obj %C_FLAGS% api-test\main.cpp
- %C_COMPILER% -o %BUILD_DIR%\main.obj %C_FLAGS% api-test\main.cpp
+ echo %C_COMPILER% -o %BUILD_DIR%\main.obj %C_FLAGS% src\main.cpp
+ %C_COMPILER% -o %BUILD_DIR%\main.obj %C_FLAGS% src\main.cpp
)
link %L_FLAGS% /OUT:%BUILD_DIR%\main.exe %BUILD_DIR%\main.obj kernel32.lib user32.lib shlwapi.lib
diff --git a/include/api-test/handle.hpp b/include/api-test/handle.hpp
deleted file mode 100644
index 2c52c01..0000000
--- a/include/api-test/handle.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-// template<typename T>
-// struct handle {
-// uint32_t id = handle::invalid_id;
-//
-// [[nodiscard]] inline bool is_valid() const { return id != handle::invalid_id; }
-//
-// static constexpr uint32_t invalid_id = -1U;
-// };
-
-template<typename U>
-struct handle {
- uint32_t id = invalid_id;
- uint32_t generation = 0U;
-
- [[nodiscard]] inline bool is_valid() const { return id != handle::invalid_id; }
-
- static constexpr uint32_t invalid_id = UINT32_MAX;
-
- // static constexpr handle<U> invalid_handle {};
-};
diff --git a/include/api-test/resource-manager.hpp b/include/api-test/resource-manager.hpp
deleted file mode 100644
index f414367..0000000
--- a/include/api-test/resource-manager.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include "handle.hpp"
-#include "freelist.hpp"
-#include "texture.hpp"
-#include "buffer.hpp"
-
-class resourcemanager {
-public:
-
- handle<texture> create_texture(const texture_desc& desc);
-
- handle<buffer> create_buffer(const buffer_desc& desc);
-
- const texture& get_texture(handle<texture> handle);
-
- const buffer& get_buffer(handle<buffer> handle);
-
-private:
- freelist<texture> textures;
- freelist<buffer> buffers;
-};
diff --git a/include/api-test/texture.hpp b/include/api-test/texture.hpp
deleted file mode 100644
index 59bfec1..0000000
--- a/include/api-test/texture.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-#include <vulkan/vulkan_core.h>
-
-#include "handle.hpp"
-
-struct device_texture;
-
-class texture {
-public:
- texture(handle<device_texture> handle);
-
-private:
- handle<device_texture> handle;
-};
diff --git a/include/api-test/vk-bindless.hpp b/include/api-test/vk-bindless.hpp
deleted file mode 100644
index a5686ff..0000000
--- a/include/api-test/vk-bindless.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-#include <cstdint>
-
-#include <vulkan/vulkan_core.h>
-
-#include "handle.hpp"
-
-enum BindlessSetType : uint32_t {
- GLOBAL,
- INSTANCES_UNIFORMS,
- DRAWS_UNIFORMS,
- MAX,
-};
-
-enum ConstantType : uint32_t {
- GLOBALS,
- INSTANCES,
- DRAWS,
- VERTEX_BUFFER
-};
-
-enum SamplerType : uint32_t {
- NEAREST,
- LINEAR,
- MAX_SAMPLER,
-};
-
-struct device_buffer;
-
-struct bindless_model {
-#ifndef USE_VK_DESCRIPTOR_BUFFER
- [[nodiscard]] device_buffer& get_draws_uniform_buffer() const;
- [[nodiscard]] device_buffer& get_globals_uniform_buffer() const;
-
- static bindless_model create_bindless_model();
-
- static void destroy_bindless_model(bindless_model& bindless);
-
- VkPipelineLayout graphics_layout;
- VkPipelineLayout compute_layout;
- VkDescriptorSet sets[BindlessSetType::MAX];
-
-private:
- static constexpr size_t max_push_constants_size = 128ULL;
-
-public:
- static constexpr size_t max_push_constants_slots_size = 8U;
- static constexpr size_t max_push_constants_slots = max_push_constants_size / max_push_constants_slots_size;
-
-private:
- VkDescriptorSetLayout sets_layout[BindlessSetType::MAX];
- VkDescriptorPool descriptor_pool;
- handle<device_buffer> globals_uniform_buffer_handle;
- handle<device_buffer> instances_uniform_buffer_handle;
- handle<device_buffer> draws_uniform_buffer_handle;
-
- static constexpr size_t descriptor_pool_allocable_sets_count = 64U;
- static constexpr uint32_t set_descriptors_count = 1024U;
-
- void create_layout(VkDevice device);
- void create_descriptor_pool(VkDevice device);
- void allocate_sets(VkDevice device);
-
- void destroy_descriptor_pool(VkDevice device);
-
- void create_immutable_samplers(VkDevice device);
-
- void destroy_immutable_samplers(VkDevice device);
-
- VkSampler samplers[SamplerType::MAX_SAMPLER];
-
- static constexpr size_t globals_uniform_buffer_size = 64ULL * 1024ULL;
- static constexpr size_t instances_uniform_buffer_size = 64ULL * 1024ULL;
- static constexpr size_t draws_uniform_buffer_size = 64ULL * 1024ULL;
-#else
- VkPipelineLayout layout;
- VkDescriptorSetLayout sets_layout[BindlessSetType::MAX];
-
- static constexpr size_t descriptor_pool_allocable_sets_count = 64U;
- static constexpr uint32_t set_descriptors_count[BindlessSetType::MAX]{ 1024U };
-
- static bindless_model create_bindless_model(VkDevice device);
-
- static void destroy_bindless_model(VkDevice device, bindless_model& bindless);
-
- private:
- void create_layout(VkDevice device);
-
- handle<device_buffer> storage_image_descriptors;
- handle<device_buffer> sampled_image_descriptors;
-#endif
-};
diff --git a/include/api-test/buffer.hpp b/include/buffer.hpp
index 64c4881..64c4881 100644
--- a/include/api-test/buffer.hpp
+++ b/include/buffer.hpp
diff --git a/include/bvh-node.hpp b/include/bvh-node.hpp
deleted file mode 100644
index 525e1c8..0000000
--- a/include/bvh-node.hpp
+++ /dev/null
@@ -1,320 +0,0 @@
-#ifndef __BVH_NODE_HPP_
-#define __BVH_NODE_HPP_
-
-#include <vector>
-#include <algorithm>
-#include <iostream>
-
-#include "aabb.hpp"
-// #include "sphere.hpp"
-#include "triangle.hpp"
-
-struct bvh_node {
- aabb bounding_box;
-
- int32_t next_id = -1;
- int32_t primitive_id = -1;
- uint32_t padding[2];
-};
-
-struct packed_bvh_node {
- float min[3];
- int32_t next_id = -1;
- float max[3];
- int32_t primitive_id = -1;
-};
-
-struct temp_node : public bvh_node {
- int32_t left_id;
- int32_t df_id;
-};
-
-class bvh {
-public:
- // bvh(std::vector<sphere>& spheres, std::vector<packed_bvh_node>& packed_nodes)
- // :spheres(spheres) {
- // packed_nodes.resize(2 * spheres.size() - 1);
- // temp_nodes = std::vector<temp_node>(2 * spheres.size() - 1);
- // leafs = std::vector<temp_node>(spheres.size());
-
- // for (uint32_t id = 0; id < spheres.size(); id++) {
- // leafs[id].bounding_box = aabb(spheres[id].center, spheres[id].radius);
- // leafs[id].primitive_id = id;
- // }
-
- // temp_nodes[0] = temp_node();
-
- // temp_nodes[0].bounding_box = compute_bounds(0, spheres.size());
- // subdivide(0, 0, spheres.size());
-
- // set_depth_first_order();
-
- // for (uint32_t id = 0; id < temp_nodes.size(); id++) {
- // auto old_node = temp_nodes[id];
- // auto &node = packed_nodes[old_node.df_id];
-
- // node.primitive_id = old_node.primitive_id;
-
- // node.min[0] = old_node.bounding_box.minimum.v[0];
- // node.min[1] = old_node.bounding_box.minimum.v[1];
- // node.min[2] = old_node.bounding_box.minimum.v[2];
-
- // node.max[0] = old_node.bounding_box.maximum.v[0];
- // node.max[1] = old_node.bounding_box.maximum.v[1];
- // node.max[2] = old_node.bounding_box.maximum.v[2];
-
- // if (old_node.next_id != -1) {
- // node.next_id = temp_nodes[old_node.next_id].df_id;
- // }
- // }
-
- // // exporter();
- // }
-
- bvh(std::vector<triangle>& triangles, std::vector<packed_bvh_node>& packed_nodes)
- :triangles(triangles) {
- packed_nodes.resize(2 * triangles.size() - 1);
- temp_nodes = std::vector<temp_node>(2 * triangles.size() - 1);
- leafs = std::vector<temp_node>(triangles.size());
-
- for (uint32_t id = 0; id < triangles.size(); id++) {
- leafs[id].bounding_box = aabb(triangles[id]);
- leafs[id].primitive_id = id;
- }
-
- temp_nodes[0] = temp_node();
-
- temp_nodes[0].bounding_box = compute_bounds(0, triangles.size());
- subdivide(0, 0, triangles.size());
-
- set_depth_first_order();
-
- for (uint32_t id = 0; id < temp_nodes.size(); id++) {
- auto old_node = temp_nodes[id];
- auto &node = packed_nodes[old_node.df_id];
-
- node.primitive_id = old_node.primitive_id;
-
- node.min[0] = old_node.bounding_box.minimum.v[0];
- node.min[1] = old_node.bounding_box.minimum.v[1];
- node.min[2] = old_node.bounding_box.minimum.v[2];
-
- node.max[0] = old_node.bounding_box.maximum.v[0];
- node.max[1] = old_node.bounding_box.maximum.v[1];
- node.max[2] = old_node.bounding_box.maximum.v[2];
-
- if (old_node.next_id != -1) {
- node.next_id = temp_nodes[old_node.next_id].df_id;
- }
- }
-
- // exporter();
- }
-
- //-------------------------
- // BVH exporter for graphviz
- //-------------------------
- void exporter() {
- std::cout << "digraph bvh {" << std::endl;
-
- traverse_depth_first(temp_nodes, 0);
-
- // traverse_depth_first_ordered(-1, 0);
-
- std::cout << "}" << std::endl;
- }
-
- bool traverse_depth_first(std::vector<temp_node>& nodes, int32_t id) {
- if (id <= 0) {
- std::cout << ";" << std::endl;
- return false;
- }
-
- std::cout << " -> " << id;
- if (traverse_depth_first(nodes, nodes[id].left_id)) {
- std::cout << "\t " << id;
- traverse_depth_first(nodes, nodes[id].left_id + 1);
- }
-
- return true;
- }
-
- int32_t traverse_depth_first_ordered(std::vector<bvh_node>& nodes, int32_t parent_id, int32_t id) {
- if (id == -1) {
- return -1;
- }
-
- if (nodes[id].primitive_id == -1) {
- int32_t left = id + 1;
- int32_t next_id;
-
- std::cout << "\t " << parent_id << " -> " << id << ";\n";
- next_id = traverse_depth_first_ordered(nodes, id, left);
-
- if (next_id != -1) {
- return traverse_depth_first_ordered(nodes, id, next_id);
- }
- } else if (nodes[id].primitive_id != -1 && nodes[id].next_id != -1) {
- std::cout << "\t " << parent_id << " -> " << id << ";\n";
- return nodes[id].next_id;
- } else {
- std::cout << "\t " << parent_id << " -> " << id << ";\n";
- }
-
- return -1;
- }
-
- std::vector<temp_node> temp_nodes;
- std::vector<temp_node> leafs;
-
- // std::vector<sphere>& spheres;
- std::vector<triangle>& triangles;
-
- uint32_t next_node_id = 0;
-
-private:
-
- static constexpr uint32_t buckets_count = 12;
-
- aabb compute_bounds(uint32_t begin, uint32_t end) {
- aabb global_box = aabb();
-
- for (uint32_t id = begin; id < end; id++) {
- global_box.union_with(leafs[id].bounding_box);
- }
-
- return global_box;
- }
-
- void subdivide(uint32_t parent_id, uint32_t begin, uint32_t end) {
- size_t count = end - begin;
- if (count == 1) {
- temp_nodes[parent_id] = leafs[begin];
- return;
- }
-
- auto left_id = ++next_node_id;
- auto right_id = ++next_node_id;
-
- temp_nodes[parent_id].left_id = left_id;
-
- if (count == 2) {
- temp_nodes[left_id] = leafs[begin];
- temp_nodes[right_id] = leafs[begin + 1];
- } else {
- auto parent_bb = temp_nodes[parent_id].bounding_box;
- int32_t split_axis = parent_bb.maximum_axis();
-
- if (count <= 4) {
- // Subdivide the node by splitting the set in two equal parts
- std::sort(leafs.begin() + begin, leafs.begin() + end,
- // [&](const bvh_node& a, const bvh_node& b) {
- // return spheres[a.primitive_id].center[split_axis] < spheres[b.primitive_id].center[split_axis];
- // }
- [&](const bvh_node& a, const bvh_node& b) {
- return triangles[a.primitive_id].center()[split_axis] < triangles[b.primitive_id].center()[split_axis];
- }
- );
-
- temp_nodes[left_id].bounding_box = compute_bounds(begin, begin + (count / 2));
- temp_nodes[right_id].bounding_box = compute_bounds(begin + (count / 2), end);
-
- subdivide(left_id, begin, begin + (count / 2));
- subdivide(right_id, begin + (count / 2), end);
- } else {
- // Subdivide based on SAH
- struct Bucket {
- uint32_t count = 0;
- aabb bb;
- };
- Bucket buckets[buckets_count];
-
- // Split the set in N spatial buckets
- // Simplify the optimal split axis search to just an axis between each bucket
- aabb centroid_bounds;
-
- for (size_t i = begin; i < end; i++) {
- auto primitive = triangles[leafs[i].primitive_id];
- centroid_bounds.union_with(primitive.center());
- // auto primitive = spheres[leafs[i].primitive_id];
- // centroid_bounds.union_with(primitive.center);
- }
-
- float split_axis_size = centroid_bounds.maximum[split_axis] - centroid_bounds.minimum[split_axis];
- for (size_t i = begin; i < end; i++) {
- auto primitive = triangles[leafs[i].primitive_id];
- auto normalized_offset = (primitive.center()[split_axis] - centroid_bounds.minimum[split_axis]) / split_axis_size;
- // auto primitive = spheres[leafs[i].primitive_id];
- // auto normalized_offset = (primitive.center[split_axis] - centroid_bounds.minimum[split_axis]) / split_axis_size;
- uint32_t bucket_index = normalized_offset * buckets_count;
- if (bucket_index == buckets_count) {
- bucket_index -= 1;
- }
-
- buckets[bucket_index].count++;
- buckets[bucket_index].bb.union_with(leafs[i].bounding_box);
- }
-
- // Compute each potential split axis cost
- float buckets_cost[buckets_count - 1] = { 0.f };
- for (size_t bucket_index = 0; bucket_index < buckets_count - 1; bucket_index++) {
- aabb right_side_bb, left_side_bb;
- float right_side_count = 0, left_side_count = 0;
-
- for (size_t i = 0; i <= bucket_index; i++) {
- left_side_bb.union_with(buckets[i].bb);
- left_side_count += buckets[i].count;
- }
-
- for (size_t i = bucket_index + 1; i < buckets_count; i++) {
- right_side_bb.union_with(buckets[i].bb);
- right_side_count += buckets[i].count;
- }
-
- float left = left_side_count * left_side_bb.surface_area();
- float right = right_side_count * right_side_bb.surface_area();
- buckets_cost[bucket_index] = 0.125f + (left + right) / parent_bb.surface_area();
- }
-
- float min_cost = buckets_cost[0];
- uint32_t min_cost_bucket = 0;
- for (size_t bucket_index = 1; bucket_index < buckets_count - 1; bucket_index++) {
- if (buckets_cost[bucket_index] < min_cost) {
- min_cost = buckets_cost[bucket_index];
- min_cost_bucket = bucket_index;
- }
- }
-
- uint32_t middle_primitive_index = buckets[0].count;
- for (size_t bucket_index = 1; bucket_index <= min_cost_bucket; bucket_index++) {
- middle_primitive_index += buckets[bucket_index].count;
- }
-
- temp_nodes[left_id].bounding_box = compute_bounds(begin, begin + middle_primitive_index);
- temp_nodes[right_id].bounding_box = compute_bounds(begin + middle_primitive_index, end);
-
- subdivide(left_id, begin, begin + middle_primitive_index);
- subdivide(right_id, begin + middle_primitive_index, end);
- }
- }
- }
-
- void set_depth_first_order() {
- int32_t df_index = 0;
- depth_first_order(0, -1, df_index);
- }
-
-
- void depth_first_order(int32_t id, int32_t next_id, int32_t &new_id) {
- auto &node = temp_nodes[id];
- node.next_id = next_id;
- node.df_id = new_id++;
-
- if (node.left_id > 0) {
- depth_first_order(node.left_id, node.left_id + 1, new_id);
- depth_first_order(node.left_id + 1, next_id, new_id);
- }
- }
-};
-
-#endif // !__BVH_NODE_HPP_
diff --git a/include/compute-renderpass.hpp b/include/compute-renderpass.hpp
deleted file mode 100644
index 6799171..0000000
--- a/include/compute-renderpass.hpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include "renderpass.hpp"
-#include "vk-api.hpp"
-
-class Texture;
-class Buffer;
-
-class ComputeRenderpass : public Renderpass {
- public:
-
- ComputeRenderpass(vkapi& api);
- ~ComputeRenderpass() override;
-
- void set_pipeline(const char* shader_name);
-
- void set_dispatch_size(size_t count_x, size_t count_y, size_t count_z);
-
- void set_ouput_texture(Texture* out_texture);
-
- 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);
-
- // TODO: Do not use vulkan api type
- void execute(vkrenderer& renderer, VkCommandBuffer command_buffer) final;
-
- Texture* output_texture;
-
- private:
-
- std::vector<Texture*> input_textures;
-
- uint8_t constants[64];
-
- size_t group_count_x;
- size_t group_count_y;
- size_t group_count_z;
-
- pipeline pipeline;
-};
diff --git a/include/api-test/dx12-command-buffer.hpp b/include/dx12-command-buffer.hpp
index e9de39a..e9de39a 100644
--- a/include/api-test/dx12-command-buffer.hpp
+++ b/include/dx12-command-buffer.hpp
diff --git a/include/api-test/dx12-device-types.hpp b/include/dx12-device-types.hpp
index 4b2fc42..4b2fc42 100644
--- a/include/api-test/dx12-device-types.hpp
+++ b/include/dx12-device-types.hpp
diff --git a/include/api-test/dx12-device.hpp b/include/dx12-device.hpp
index baa5b60..baa5b60 100644
--- a/include/api-test/dx12-device.hpp
+++ b/include/dx12-device.hpp
diff --git a/include/api-test/freelist.hpp b/include/freelist.hpp
index cbcd56d..2df1ca5 100644
--- a/include/api-test/freelist.hpp
+++ b/include/freelist.hpp
@@ -1,10 +1,9 @@
#pragma once
-#include <vector>
-#include <cassert>
+#include "utils.hpp"
#include "handle.hpp"
-static constexpr uint32_t default_element_count = 1024U;
+static constexpr u32 default_element_count = 1024U;
template<typename T, const size_t initial_size = default_element_count>
class freelist {
@@ -31,6 +30,8 @@ class freelist {
// elements[0U].next_free = element.next_free;
element.item = std::move(item);
+ assert(element.generation + 1 != UINT32_MAX);
+
return { id, ++element.generation };
}
@@ -54,9 +55,21 @@ class freelist {
static constexpr uint32_t invalid_id = UINT32_MAX;
+ struct element {
+ union {
+ T item;
+ uint32_t next_free = freelist<T>::invalid_id;
+ };
+ uint32_t generation = 0U;
+ };
+
+ const std::vector<freelist::element>& get_list() const {
+ return elements;
+ }
+
private:
void grow(size_t grow_size) {
- auto size = elements.size();
+ size_t size = elements.size();
uint32_t next_free = static_cast<uint32_t>(size);
next_free_id = next_free;
@@ -70,17 +83,11 @@ private:
);
}
+ // this makes it impossible to know
+ elements.back().next_free = freelist<T>::invalid_id;
elements.back().next_free = freelist<T>::invalid_id;
}
- struct element {
- union {
- T item;
- uint32_t next_free = freelist<T>::invalid_id;
- };
- uint32_t generation = 0U;
- };
-
std::vector<element> elements;
uint32_t next_free_id;
};
@@ -97,7 +104,7 @@ class idlist {
// auto id = elements[0U].next_free;
auto id = next_free_id;
- if (id == idlist<T>::invalid_id) {
+ if (id == idlist::invalid_id) {
grow(elements.size());
// id = elements[0U].next_free;
@@ -107,7 +114,7 @@ class idlist {
auto& element = elements[id];
next_free_id = element.next_free;
elements[0U].next_free = element.next_free;
- element.next_free = idlist<T>::invalid_id;
+ element.next_free = idlist::invalid_id;
return { id, ++element.generation };
}
@@ -138,11 +145,11 @@ private:
);
}
- elements.back().next_free = idlist<T>::invalid_id;
+ elements.back().next_free = idlist::invalid_id;
}
struct element {
- uint32_t next_free = idlist<T>::invalid_id;
+ uint32_t next_free = idlist::invalid_id;
uint32_t generation = 0U;
};
diff --git a/include/handle.hpp b/include/handle.hpp
new file mode 100644
index 0000000..484b217
--- /dev/null
+++ b/include/handle.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <cstdint>
+
+template<typename U>
+struct handle {
+ uint32_t id = invalid_id;
+ uint32_t generation = 0U;
+
+ [[nodiscard]] inline bool is_valid() const { return id != handle::invalid_id; }
+
+ static constexpr uint32_t invalid_id = UINT32_MAX;
+};
diff --git a/include/primitive-renderpass.hpp b/include/primitive-renderpass.hpp
deleted file mode 100644
index 95562fe..0000000
--- a/include/primitive-renderpass.hpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-#include <vector>
-
-#include "renderpass.hpp"
-#include "vk-renderer.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) 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;
-
- framebuffer framebuffers[vkrenderer::virtual_frames_count];
-
- std::vector<Primitive*> primitives;
-};
-
-
-class Primitive {
- public:
-
- Primitive(PrimitiveRenderpass& render_pass);
-
- void set_pipeline(const char* 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* 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 indices_off, off_t vertex_off);
-
- void render(VkCommandBuffer command_buffer);
-
-
-private:
-
- vkapi& api;
-
- PrimitiveRenderpass& primitive_render_pass;
-
- pipeline pipeline;
-
- Buffer* index_buffer;
-
- size_t element_count;
- off_t indices_offset;
- off_t vertex_offset;
-
- off_t constant_offset;
-
- VkRect2D scissor = {};
-
- uint8_t constants[64];
-};
diff --git a/include/renderpass.hpp b/include/renderpass.hpp
deleted file mode 100644
index da116dd..0000000
--- a/include/renderpass.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-using VkCommandBuffer = struct VkCommandBuffer_T*;
-
-class vkrenderer;
-class vkapi;
-
-class Renderpass {
- public:
-
- Renderpass(vkapi& api)
- :api(api)
- {};
-
- virtual ~Renderpass() = default;
-
- // TODO: Do not use vulkan api type
- virtual void execute(vkrenderer& renderer, VkCommandBuffer command_buffer) = 0;
-
- protected:
- vkapi &api;
-};
diff --git a/include/texture.hpp b/include/texture.hpp
index aac7b69..59bfec1 100644
--- a/include/texture.hpp
+++ b/include/texture.hpp
@@ -1,83 +1,17 @@
-#include <cstdint>
-
-using VkImage = struct VkImage_T*;
-
-struct TextureDesc {
- VkImageType type;
- VkFormat format;
- VkExtent size;
- VkImageUsageFlags usages;
-};
-
-class Texture {
- public:
- Texture(const TextureDesc desc)
- : description(desc) {
- create_device_image();
- }
-
- // Texture(handle image_handle) {
- // const auto& image = vkrenderer::api.get_image(image_handle);
- // width = image.size.width;
- // height = image.size.height;
- // depth = image.size.depth;
-
- // device_image = image_handle;
- // }
-
- // Texture(size_t width, size_t height, size_t depth, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, Sampler* texture_sampler = nullptr)
- // : width(width), height(height), depth(depth) {
- // sampler = texture_sampler;
- // device_image = vkrenderer::api.create_image(
- // { .width = (uint32_t)width, .height = (uint32_t)height, .depth = 1 },
- // format,
- // VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
- // }
+#pragma once
- void update(void* new_data) {
- if (data == nullptr) {
- free(data);
- }
- data = new_data;
-
- vkrenderer::queue_image_update(this);
- }
-
- ~Texture() {
- vkrenderer::api.destroy_image(device_image);
-
- if (data == nullptr) {
- free(data);
- }
- }
-
- [[nodiscard]] size_t size() const {
- const auto& image = vkrenderer::api.get_image(device_image);
- return width * height * depth * pixel_size(image.format);
- }
-
- static size_t pixel_size(VkFormat format) {
- switch (format) {
- case VK_FORMAT_R8G8B8A8_UNORM:
- return 4;
- default:
- return 0;
- }
- }
-
- // Sampler* sampler = nullptr;
+#include <cstdint>
- private:
- void create_device_image();
+#include <vulkan/vulkan_core.h>
- void* data = nullptr;
+#include "handle.hpp"
- size_t width = 0;
- size_t height = 0;
- size_t depth = 0;
+struct device_texture;
- TextureDesc description;
+class texture {
+public:
+ texture(handle<device_texture> handle);
- VmaAllocationInfo alloc_info;
- VkImage device_image;
+private:
+ handle<device_texture> handle;
};
diff --git a/include/vk-api.hpp b/include/vk-api.hpp
deleted file mode 100644
index a3442f1..0000000
--- a/include/vk-api.hpp
+++ /dev/null
@@ -1,219 +0,0 @@
-#ifndef __VK_API_HPP_
-#define __VK_API_HPP_
-
-#include <cassert>
-#include <vector>
-
-#include <vulkan/vulkan_core.h>
-
-using VmaAllocation = struct VmaAllocation_T*;
-
-struct buffer {
- VmaAllocation alloc;
- void* device_ptr;
- VkBuffer handle;
- size_t size;
- VkDeviceAddress device_address;
-};
-
-struct pipeline {
- std::vector<VkShaderModule> shader_modules;
- VkPipeline handle = VK_NULL_HANDLE;
- VkPipelineBindPoint bind_point;
-};
-
-using bindless_index = uint32_t;
-using handle = uint32_t;
-
-struct image {
- VkImage handle;
- VkImageView view;
- VmaAllocation alloc;
- VkImageSubresourceRange subresource_range;
- VkFormat format;
- VkExtent3D size;
- VkImageUsageFlags usages;
- bindless_index bindless_storage_index = 0;
- bindless_index bindless_sampled_index = 0;
-
- VkImageLayout previous_layout = VK_IMAGE_LAYOUT_UNDEFINED;
- VkPipelineStageFlags previous_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- VkAccessFlags previous_access = 0;
-};
-
-struct swapchain {
- 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;
-};
-
-struct global_descriptor {
- VkDescriptorSetLayout set_layout;
- VkPipelineLayout pipeline_layout;
- VkDescriptorSet set;
-
- std::vector<uint32_t> index_pool[3];
-
- static constexpr uint32_t pool_size = 1024U;
-
- global_descriptor() {
- for (int32_t index = pool_size; index > 0; index--) {
- index_pool[0].push_back((uint32_t)index);
- index_pool[1].push_back((uint32_t)index);
- index_pool[2].push_back((uint32_t)index);
- }
- }
-
- uint32_t allocate(VkDescriptorType type) {
- auto& pool = index_pool[descriptor_type_binding(type)];
- auto index = pool.back();
- pool.pop_back();
-
- return index;
- }
-
- void free(uint32_t index, VkDescriptorType type) {
- assert(index != 0);
- index_pool[descriptor_type_binding(type)].push_back(index);
- }
-
- static int32_t descriptor_type_binding(VkDescriptorType type) {
- switch (type) {
- case VK_DESCRIPTOR_TYPE_SAMPLER:
- return 0;
- case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
- return 1;
- case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
- return 2;
- default:
- assert(true && "descriptor type not supported");
- return -1;
- }
- }
-};
-
-class window;
-class vkcontext;
-
-class vkapi {
- public:
- vkapi(vkcontext& context);
- ~vkapi();
-
- handle create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, uint32_t 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, size_t size, size_t buffer_offset = 0);
- void destroy_buffer(handle buffer);
-
-
- 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>& imgs);
-
-
- [[nodiscard]] VkFence create_fence() const;
- void destroy_fence(VkFence fence) const;
- [[nodiscard]] std::vector<VkFence> create_fences(size_t fences_count) const;
- void destroy_fences(VkFence fences[], size_t fences_count) const;
-
-
- [[nodiscard]] VkSemaphore create_semaphore() const;
- void destroy_semaphore(VkSemaphore semaphore) const;
- [[nodiscard]] std::vector<VkSemaphore> create_semaphores(size_t semaphores_count) const;
- void destroy_semaphores(VkSemaphore semaphores[], size_t semaphores_count) const;
-
- handle create_sampler(VkFilter filter, VkSamplerAddressMode address_mode);
- void destroy_sampler(handle sampler);
-
-
- [[nodiscard]] VkCommandPool create_command_pool() const;
-
- void allocate_command_buffers(VkCommandPool command_pool, VkCommandBuffer* command_buffers, size_t count) const;
-
-
- VkRenderPass create_render_pass(std::vector<VkFormat>& color_attachments_format, VkImageLayout initial_layout, VkImageLayout final_layout);
- VkRenderPass create_render_pass(std::vector<VkFormat>& color_attachments_format, VkFormat depth_attachement_format);
- void destroy_render_pass(VkRenderPass render_pass);
-
-
- 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) const;
- void destroy_framebuffers(std::vector<framebuffer>& framebuffers) const;
-
-
- pipeline create_compute_pipeline(const char* shader_name) const;
- pipeline create_graphics_pipeline(const char* shader_name, VkShaderStageFlagBits shader_stages, VkRenderPass render_pass, std::vector<VkDynamicState>& dynamic_states) const;
- void destroy_pipeline(pipeline& pipeline) const;
-
-
- VkSurfaceKHR create_surface(window& wnd) const;
- void destroy_surface(VkSurfaceKHR surface);
-
-
- swapchain create_swapchain(VkSurfaceKHR surface, size_t min_image_count, VkImageUsageFlags usages, VkSwapchainKHR old_swapchain);
- void destroy_swapchain(swapchain& swapchain);
-
- 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, handle image);
-
- 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, handle index_buffer, uint32_t primitive_count, uint32_t indices_offset, uint32_t vertices_offset);
-
- void blit_full(VkCommandBuffer command_buffer, handle src_image, handle dst_image);
-
- void end_record(VkCommandBuffer command_buffer);
-
- VkResult submit(VkCommandBuffer command_buffers[], size_t command_buffers_count, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const;
-
- VkResult present(swapchain& swapchain, uint32_t image_index, VkSemaphore wait_semaphore) const;
-
- 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:
- global_descriptor bindless_descriptor;
-
- static const char* shader_stage_extension(VkShaderStageFlags shader_stage);
-
- // TODO: Use freelists instead
- std::vector<buffer*> buffers;
- std::vector<image*> images;
- std::vector<sampler*> samplers;
-
- VkDescriptorPool descriptor_pool;
-};
-
-#endif // !__VK_API_HPP_
diff --git a/include/vk-bindless.hpp b/include/vk-bindless.hpp
new file mode 100644
index 0000000..008e420
--- /dev/null
+++ b/include/vk-bindless.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <vulkan/vulkan_core.h>
+
+#include "handle.hpp"
+
+enum UniformTypes : uint32_t {
+ GLOBAL,
+ PASS,
+ DRAW,
+ MAX,
+};
+
+enum SamplerType : uint32_t {
+ NEAREST,
+ LINEAR,
+ MAX_SAMPLER,
+};
+
+struct device_buffer;
+
+struct bindless_model {
+ [[nodiscard]] device_buffer& get_uniform_buffer(enum UniformTypes type) const;
+
+ void init();
+
+ void deinit();
+
+ VkPipelineLayout global_layout;
+ VkDescriptorSet global_set;
+
+public:
+ static constexpr size_t push_constant_slot_size = sizeof(uintptr_t);
+ static constexpr size_t push_constant_slots = 3U;
+
+private:
+ VkDescriptorSetLayout global_set_layout;
+ VkDescriptorPool descriptor_pool;
+ handle<device_buffer> uniform_buffers[UniformTypes::MAX];
+
+ static constexpr size_t descriptor_pool_allocable_sets_count = 64U;
+ static constexpr uint32_t set_descriptors_count = 1024U;
+
+ VkSampler samplers[SamplerType::MAX_SAMPLER];
+
+ static constexpr size_t globals_uniform_buffer_size = 64 * KB;
+ static constexpr size_t passes_uniform_buffer_size = 64 * KB;
+ static constexpr size_t draws_uniform_buffer_size = 64 * KB;
+};
diff --git a/include/api-test/vk-command-buffer.hpp b/include/vk-command-buffer.hpp
index 08652fd..82d5439 100644
--- a/include/api-test/vk-command-buffer.hpp
+++ b/include/vk-command-buffer.hpp
@@ -1,37 +1,17 @@
#pragma once
-#include <cstdint>
-#include <span>
-
-#include <vulkan/vulkan_core.h>
-
#include "handle.hpp"
-
-#include "vec3.hpp"
-
#include "vk-device-types.hpp"
+#include "vec3.hpp"
struct device_texture;
struct device_buffer;
struct device_pipeline;
struct dispatch_params {
- enum class PARAM_BINDING : uint32_t {
- PARAM1,
- PARAM2,
- PARAM3,
- PARAM4,
- PARAM5,
- PARAM6,
- PARAM7,
- PARAM8,
- MAX
- };
-
handle<device_pipeline> pipeline;
vec3u group_size;
vec3u local_group_size;
- uint64_t params[static_cast<uint32_t>(PARAM_BINDING::MAX)];
};
struct renderpass_params {
@@ -54,10 +34,6 @@ struct draw_params {
uint32_t vertex_count;
uint32_t vertex_offset;
uint32_t instance_count;
- uint64_t globals_address = 0U; // TODO: This is probably stupid and should be set elsewhere once ???
- uint64_t instances_address = 0U;
- uint64_t uniforms_address = 0U;
- uint64_t vertex_address = 0U;
};
struct draw_indexed_params {
@@ -67,10 +43,6 @@ struct draw_indexed_params {
uint32_t vertex_offset;
uint32_t index_offset;
uint32_t instance_count;
- uint64_t globals_address = 0U; // TODO: This is probably stupid and should be set elsewhere once ???
- uint64_t instances_address = 0U;
- uint64_t uniforms_address = 0U;
- uint64_t vertex_address = 0U;
};
struct command_buffer {
diff --git a/include/vk-context.hpp b/include/vk-context.hpp
deleted file mode 100644
index 0dfd256..0000000
--- a/include/vk-context.hpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-
-#include <vulkan/vulkan_core.h>
-
-using VmaAllocator = struct VmaAllocator_T*;
-
-struct queue {
- VkQueue handle;
- uint32_t index;
- VkQueueFlags usages;
-};
-
-class vkcontext {
- public:
- vkcontext();
-
- ~vkcontext();
-
- VkInstance instance;
-
- VkPhysicalDevice physical_device;
- VkDevice device;
-
- VmaAllocator allocator;
-
- queue graphics_queue;
-
- private:
- void create_instance();
-
- void create_debugger();
-
- void create_device();
-
- void create_memory_allocator();
-
- void select_physical_device();
-
- [[nodiscard]] uint32_t select_queue(VkQueueFlags queue_usage) const;
-
- static void check_available_instance_layers(const char* needed_layers[], size_t needed_layers_count);
-
- static void check_available_instance_extensions(const char* needed_extensions[], size_t needed_extensions_count);
-
- static bool support_required_features(VkPhysicalDevice physical_device);
-
-
- VkDebugUtilsMessengerEXT debugMessenger;
-};
diff --git a/include/api-test/vk-device-types.hpp b/include/vk-device-types.hpp
index eddf40c..94f9560 100644
--- a/include/api-test/vk-device-types.hpp
+++ b/include/vk-device-types.hpp
@@ -1,8 +1,6 @@
#pragma once
-#include <vulkan/vulkan_core.h>
-
-#include <span>
+#include <cstdint>
#include "freelist.hpp"
@@ -60,6 +58,8 @@ struct device_texture {
uint32_t depth = 1U;
uint32_t mips = 1U;
+ const char* name = nullptr;
+
private:
handle<void> storage_index;
handle<void> sampled_index;
@@ -110,52 +110,56 @@ struct buffer_desc {
VkBufferUsageFlags usages;
VkMemoryPropertyFlags memory_properties;
uint32_t memory_usage;
+ const char* name;
};
-#define ALIGN(value, alignment) \
- (((value) + ((alignment) - 1)) & ~((alignment) - 1))
-
struct device_buffer {
template<typename T>
T* allocate() {
- // size_t alloc_size = (sizeof(T) + 0x100) & 0xffffff00;
- size_t alloc_size = ALIGN(sizeof(T), 16);
- if (offset + alloc_size > size) {
+ u32 alloc_size = sizeof(T);
+ if (allocated_size + alloc_size > size) {
reset();
}
- auto* addr = (T*)(static_cast<uint8_t*>(mapped_ptr) + offset);
- offset += alloc_size;
+ offset = allocated_size;
+ T* addr = (T*)(static_cast<uint8_t*>(mapped_ptr) + offset);
+ allocated_size += alloc_size;
return addr;
}
- void* allocate(uint64_t alloc_size) {
- // size_t alloc_size = (sizeof(T) + 0x100) & 0xffffff00;
- alloc_size = ALIGN(alloc_size, 16);
- if (offset + alloc_size > size) {
+ void* allocate(u32 alloc_size) {
+ if (allocated_size + alloc_size > size) {
reset();
}
- auto* addr = (void*)(static_cast<uint8_t*>(mapped_ptr) + offset);
- offset += alloc_size;
+ offset = allocated_size;
+ void* addr = (void*)(static_cast<uint8_t*>(mapped_ptr) + offset);
+ allocated_size += alloc_size;
return addr;
}
void reset() {
+ allocated_size = 0U;
offset = 0U;
}
- uint64_t offset = 0U;
- VkBuffer vk_buffer;
- VmaAllocation alloc;
- VkDeviceAddress device_address = 0U;
- void* mapped_ptr;
- size_t size;
+ u32 offset = 0U;
+ u32 allocated_size = 0U;
+ VkBuffer vk_buffer;
+ VmaAllocation alloc;
+ VkDeviceAddress device_address = 0U;
+ void* mapped_ptr;
+ size_t size;
+ VkBufferUsageFlagBits2 usages;
+
+ const char* name;
};
struct graphics_pipeline_desc {
- std::span<uint8_t> vs_code;
- std::span<uint8_t> fs_code;
+ uint8_t* vs_code;
+ size_t vs_code_size;
+ uint8_t* fs_code;
+ size_t fs_code_size;
std::span<VkFormat> color_attachments_format;
VkFormat depth_attachment_format;
VkFormat stencil_attachment_format;
@@ -163,7 +167,8 @@ struct graphics_pipeline_desc {
};
struct compute_pipeline_desc {
- std::span<uint8_t> cs_code;
+ uint8_t* cs_code;
+ size_t cs_code_size;
const char* name;
};
diff --git a/include/api-test/vk-device.hpp b/include/vk-device.hpp
index 1b04bb3..e2e8c99 100644
--- a/include/api-test/vk-device.hpp
+++ b/include/vk-device.hpp
@@ -1,13 +1,8 @@
#pragma once
-#include <cstdint>
-#include <span>
-
-#include <vulkan/vulkan_core.h>
-
#include "freelist.hpp"
-#include "vk-device-types.hpp"
#include "vk-bindless.hpp"
+#include "vk-command-buffer.hpp"
using VmaAllocator = struct VmaAllocator_T*;
@@ -16,17 +11,17 @@ class window;
class vkdevice {
struct queue {
- VkQueue vk_queue;
- uint32_t index;
+ VkQueue vk_queue = VK_NULL_HANDLE;
+ uint32_t index = UINT32_MAX;
VkQueueFlags usages;
- VkCommandPool command_pool;
+ VkCommandPool command_pool = VK_NULL_HANDLE;
};
public:
void init();
void deinit();
- static inline vkdevice& get_render_device() {
+ static inline vkdevice& get() {
return render_device;
}
@@ -89,7 +84,11 @@ class vkdevice {
return bindless;
}
- inline VkDevice get_device() {
+ const freelist<device_texture>& get_textures() const {
+ return textures;
+ }
+
+ inline VkDevice get_device() const {
return device;
}
@@ -97,6 +96,10 @@ class vkdevice {
return gpu_allocator;
}
+ inline const VkPhysicalDeviceLimits& get_device_limits() const {
+ return physical_device_props.properties.limits;
+ }
+
// uint64_t submit(std::span<command_buffer> buffers, handle<device_semaphore> wait_handle, handle<device_semaphore> signal_handle, handle<device_semaphore> fence_handle);
uint32_t acquire_image_index(handle<device_surface> surface_handle);
uint64_t submit_before_present(handle<device_surface> surface_handle, command_buffer* buffers, uint32_t count);
@@ -112,8 +115,6 @@ class vkdevice {
void allocate_command_buffers(command_buffer* buffers, size_t count, QueueType type, const char* name);
- VkShaderModule create_shader_module(const std::span<uint8_t>& shader_code);
-
void create_swapchain(const surface_desc& desc, device_surface& surface);
// TODO: Wrap in a struct called adapter ?
@@ -127,7 +128,7 @@ class vkdevice {
void pick_physical_device();
- static bool device_support_features(VkPhysicalDevice physical_dev);
+ bool device_support_features(VkPhysicalDevice physical_dev);
void create_debug_layer_callback();
@@ -135,6 +136,7 @@ class vkdevice {
VkInstance instance;
VkPhysicalDevice physical_device;
+ VkPhysicalDeviceProperties2 physical_device_props;
VkDevice device;
VmaAllocator gpu_allocator;
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
deleted file mode 100644
index 1317912..0000000
--- a/include/vk-renderer.hpp
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifndef __VK_RENDERER_HPP_
-#define __VK_RENDERER_HPP_
-
-#include <cstdint>
-#include <format>
-#include <vector>
-
-#include "vk-context.hpp"
-#include "vk-api.hpp"
-
-
-class Renderpass;
-class ComputeRenderpass;
-class PrimitiveRenderpass;
-class Primitive;
-class window;
-
-class Texture;
-class Sampler;
-class RingBuffer;
-
-
-class Buffer {
- public:
-
- Buffer(size_t size, VkBufferUsageFlagBits usage);
- ~Buffer();
-
- void write(void* data, off_t alloc_offset, size_t data_size) const;
-
- void resize(size_t new_size);
-
- handle device_buffer;
-
- size_t buffer_size;
-
- VkBufferUsageFlagBits usage;
-};
-
-
-class vkrenderer {
- public:
- vkrenderer(window& wnd);
-
- ~vkrenderer();
-
- void recreate_swapchain();
-
-
- void update_images();
-
- void begin_frame();
-
- void finish_frame();
-
- static void queue_image_update(Texture* texture);
-
- static Buffer* create_buffer(size_t size);
-
- static Buffer* create_index_buffer(size_t size);
-
- static Buffer* create_staging_buffer(size_t size);
-
- static 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();
-
- [[nodiscard]]uint32_t frame_index() const { return this->virtual_frame_index; }
-
- [[nodiscard]]Texture* back_buffer() const { return swapchain_textures[swapchain_image_index]; }
-
- [[nodiscard]]VkFormat back_buffer_format() const { return swapchain.surface_format.format; }
-
- static constexpr uint32_t virtual_frames_count = 2;
-
- static vkcontext context;
-
- static vkapi api;
-
- private:
-
-
- void handle_swapchain_result(VkResult function_result);
-
- std::vector<Renderpass*> renderpasses;
-
- uint32_t virtual_frame_index = 0;
- uint32_t swapchain_image_index = 0;
-
- VkCommandBuffer graphics_command_buffers[virtual_frames_count];
- VkCommandBuffer copy_command_buffers[virtual_frames_count];
-
- RingBuffer* staging_buffers[virtual_frames_count];
-
-
- pipeline tonemapping_pipeline;
-
- VkFence submission_fences[virtual_frames_count];
- VkSemaphore execution_semaphores[virtual_frames_count];
- VkSemaphore acquire_semaphores[virtual_frames_count];
-
- VkCommandPool graphics_command_pool;
- VkCommandPool copy_command_pools[virtual_frames_count];
-
- VkSurfaceKHR platform_surface;
- swapchain swapchain;
- std::vector<Texture*> swapchain_textures;
- std::vector<VkCommandBuffer> recorded_command_buffers;
-
- const uint32_t min_swapchain_image_count = 3;
-
- static std::vector<Texture*> upload_queue;
-};
-
-class RingBuffer {
- public:
-
- static const size_t invalid_alloc = -1;
-
- RingBuffer(size_t size);
-
- [[nodiscard]]size_t alloc(size_t alloc_size) {
- assert(alloc_size > 0 && alloc_size <= buffer_size);
-
- auto alloc_offset = ptr;
-
- if (alloc_offset <= buffer_size - alloc_size) {
- ptr += alloc_size;
- return alloc_offset;
- }
-
- return invalid_alloc;
- }
-
- void write(void* data, size_t alloc_offset, size_t data_size) const {
- auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
-
- std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
- }
-
- void reset() {
- ptr = 0;
- }
-
- handle device_buffer;
-
- size_t buffer_size;
- size_t ptr = 0;
-};
-
-class Sampler {
- public:
-
- handle device_sampler;
-};
-
-#endif // !__VK_RENDERER_HPP_
diff --git a/include/api-test/vk-utils.hpp b/include/vk-utils.hpp
index 205e103..f26d2a3 100644
--- a/include/api-test/vk-utils.hpp
+++ b/include/vk-utils.hpp
@@ -1,13 +1,9 @@
#pragma once
-#include <cassert>
-
-#include <vulkan/vulkan_core.h>
-
#ifdef _DEBUG
#define VKCHECK(result) assert((result) == VK_SUCCESS)
#else
-#define VKCHECK(result) result
+#define VKCHECK(result) (void)result
#endif
VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
diff --git a/src/compute-renderpass.cpp b/src/compute-renderpass.cpp
deleted file mode 100644
index d5dbaa0..0000000
--- a/src/compute-renderpass.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "compute-renderpass.hpp"
-
-#include "vk-renderer.hpp"
-
-ComputeRenderpass::ComputeRenderpass(vkapi& api)
- : Renderpass(api)
-{}
-
-ComputeRenderpass::~ComputeRenderpass() {
- api.destroy_pipeline(pipeline);
-}
-
-void ComputeRenderpass::set_pipeline(const char* shader_name) {
- if (this->pipeline.handle != VK_NULL_HANDLE)
- api.destroy_pipeline(this->pipeline);
- this->pipeline = api.create_compute_pipeline(shader_name);
-}
-
-void ComputeRenderpass::set_ouput_texture(Texture* out_texture) {
- this->output_texture = out_texture;
-
- const auto& image = api.get_image(output_texture->device_image);
-
- // TODO: Remove hardcoded offset
- memcpy(constants + 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) {
- group_count_x = count_x;
- group_count_y = count_y;
- group_count_z = count_z;
-}
-
-void ComputeRenderpass::set_constant(off_t offset, uint64_t* constant) {
- memcpy(constants + offset, constant, sizeof(uint64_t));
-}
-
-void ComputeRenderpass::set_constant(off_t offset, Texture* texture) {
- const auto& image = api.get_image(texture->device_image);
-
- memcpy(constants + offset, (void*)&image.bindless_storage_index, sizeof(bindless_index));
-
- input_textures.push_back(texture);
-}
-
-void ComputeRenderpass::set_constant(off_t offset, Buffer* buffer) {
- auto device_buffer = api.get_buffer(buffer->device_buffer);
- memcpy(constants + offset, (void*)&device_buffer.device_address, sizeof(VkDeviceAddress));
-}
-
-void ComputeRenderpass::execute(vkrenderer&, VkCommandBuffer command_buffer) {
- api.update_constants(command_buffer, VK_SHADER_STAGE_COMPUTE_BIT, 0, 64, (void*)&constants);
-
- for (auto& texture: input_textures) {
- api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT, texture->device_image);
- }
-
- api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_SHADER_WRITE_BIT, output_texture->device_image);
-
- api.run_compute_pipeline(command_buffer, pipeline, group_count_x, group_count_y, group_count_z);
-
- input_textures.clear();
-}
diff --git a/api-test/dx12-command-buffer.cpp b/src/dx12-command-buffer.cpp
index 0310dfd..0310dfd 100644
--- a/api-test/dx12-command-buffer.cpp
+++ b/src/dx12-command-buffer.cpp
diff --git a/api-test/dx12-device.cpp b/src/dx12-device.cpp
index ac328ed..ac328ed 100644
--- a/api-test/dx12-device.cpp
+++ b/src/dx12-device.cpp
diff --git a/src/main.cpp b/src/main.cpp
index 1acf2fb..4d56a3c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,437 +1,840 @@
-#include <chrono>
-#include <filesystem>
+// ===============
+// windows.h stuff
+// ===============
+#if defined(_WIN32)
+ #if defined(_M_AMD64)
+ #define _AMD64_
+ #endif
+ #include <basetsd.h>
+ #include <windef.h>
+ #include <winnt.h>
+ #include <winbase.h>
+ #include <winuser.h>
+ #include <winnls.h>
+ #include <fileapi.h>
+ #include <shlwapi.h>
+ #include <handleapi.h>
+ #include <errhandlingapi.h>
+#endif // _WIN32
-#include "imgui.h"
-#ifdef ENABLE_RENDERDOC
-#include <renderdoc.h>
-#endif
-#include "compute-renderpass.hpp"
-#include "primitive-renderpass.hpp"
-#include "scene.hpp"
-#include "vk-renderer.hpp"
-#include "window.hpp"
-#include "utils.hpp"
+// -------------------
+// thirdparties
+// -------------------
+#define IMGUI_DISABLE_WIN32_FUNCTIONS
+#include "imgui.cpp"
+#include "imgui_draw.cpp"
+#include "imgui_tables.cpp"
+#include "imgui_widgets.cpp"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include <stb_image.h>
+
+#include <simdjson.h>
+#include "simdjson.cpp"
+
+#define ENABLE_RENDERDOC 1
+#if ENABLE_RENDERDOC
+#include <renderdoc_app.h>
-#if defined(LINUX)
-#include <dlfcn.h>
-#include <unistd.h>
-#elif defined(WINDOWS)
-#include <Windows.h>
+
+
+#define RD_START_CAPTURE if(rdoc_api != nullptr) rdoc_api->StartFrameCapture(nullptr, nullptr)
+#define RD_END_CAPTURE if(rdoc_api != nullptr) rdoc_api->EndFrameCapture(nullptr, nullptr)
+#else
+#define RD_START_CAPTURE
+#define RD_END_CAPTURE
+#endif // ENABLE_RENDERDOC
+
+#define VK 1
+#define DX12 0
+#if DX12
+#include "dx12-device.hpp"
+#include "dx12-command-buffer.hpp"
+#else
+#include "vulkan-loader.cpp"
+#include "vk-utils.cpp"
+#include "vk-device.cpp"
+#include "vk-bindless.cpp"
+#include "vk-command-buffer.cpp"
#endif
-struct VkVertex {
- float x, y;
- float u, v;
- uint32_t color;
- uint32_t padding[3];
-};
+#include "vec3.cpp"
+#include "utils.cpp"
+#include "window.cpp"
+#include "camera.cpp"
+#include "mesh.cpp"
+#include "gltf.cpp"
+#include "bvh.cpp"
+#include "scene.cpp"
+
+
+
+// -------------------
+// GLOBALS
+// -------------------
+LARGE_INTEGER freq;
+std::vector<handle<device_texture>> debug_texture_list;
+
+#if ENABLE_RENDERDOC
+RENDERDOC_API_1_6_0 *rdoc_api = nullptr;
+#endif // ENABLE_RENDERDOC
+
+void watch_func() {
+ printf("change");
+}
+
+void ui(scene* scene, float frame_time) {
+ static float max_fps = 0.f;
+ static float max_frame_time = 0.f;
+ float fps = 1000U / (frame_time > 0.001f ? frame_time : 0.001f);
+ if (fps > max_fps) {
+ max_fps = fps;
+ }
+ if (frame_time > max_frame_time) {
+ max_frame_time = frame_time;
+ }
-void update_ui(scene& main_scene, float delta_time) {
ImGui::NewFrame();
+ const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
+ ImGuiWindowFlags wnd_flags = ImGuiWindowFlags_NoMove;
+ ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkSize.x - 250, main_viewport->WorkPos.y), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(250, 720), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowPos({0.f, 0.f});
- ImGui::SetNextWindowSize({0.f, 0.f});
- ImGui::Begin("Debug", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar);
+ ImGui::Begin("Debug", nullptr, wnd_flags);
+ if (ImGui::CollapsingHeader("Perfs")) {
+ ImGui::SeparatorText("Metrics");
+ ImGui::Text("FPS : %f\n", fps);
+ ImGui::Text("Max FPS : %f\n", max_fps);
+ ImGui::Text("frame_time : %f ms\n", frame_time);
+ ImGui::Text("max frame_time : %f ms\n", max_frame_time);
- 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::SeparatorText("Markers");
+ for (uint32_t index = 0U; index < marker_count; index++ ) {
+ uint64_t diff = marker_counter_end[index] - marker_counter_start[index];
+ uint64_t time = (diff * 1000000ULL) / freq.QuadPart;
- if (ImGui::Checkbox("depth of field", (bool*)&main_scene.meta.enable_dof)) {
- main_scene.meta.sample_index = 1;
+ ImGui::Text("%s time : %f ms\n", marker_names[index], static_cast<float>(time) / 1000U);
+ }
}
- 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::CollapsingHeader("Images")) {
+ for (const handle<device_texture>& handle : debug_texture_list) {
+ const device_texture& tex = vkdevice::get().get_texture(handle);
+ const char* name = tex.name;
+ ImGui::Text(name ? name : DUMMY_NAME);
+ ImGui::Image(tex.get_sampled_index(), ImVec2(128, 128));
+ }
}
- if (ImGui::Checkbox("debug bvh", (bool *)&main_scene.meta.debug_bvh)) {
- main_scene.meta.sample_index = 1;
+ if (ImGui::CollapsingHeader("Scene")) {
+ ImGui::SliderInt("Max bounce", reinterpret_cast<int*>(&scene->meta.max_bounce), 5, 100);
+ ImGui::SliderInt("Min bounce", reinterpret_cast<int*>(&scene->meta.min_bounce), 1, 5);
+
+ ImGui::Checkbox("DOF", reinterpret_cast<bool*>(&scene->meta.enable_dof));
+ ImGui::Checkbox("Debug BVH", reinterpret_cast<bool*>(&scene->meta.debug_bvh));
+ if (ImGui::SliderInt("Scale facotr", reinterpret_cast<int*>(&scene->meta.downscale_factor), 1, 20)) {
+ scene->meta.sample_index = 1U;
+ }
}
ImGui::End();
- bool open = true;
- ImGui::ShowDemoWindow(&open);
-
ImGui::EndFrame();
-
ImGui::Render();
}
-void render(scene& main_scene, vkrenderer& renderer) {
- // 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);
+int main() {
+ // From Microsoft doc
+ // https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancefrequency
+ // The frequency of the performance counter is fixed at system boot and is
+ // consistent across all processors so you only need to query the frequency
+ // from QueryPerformanceFrequency as the application initializes,
+ // and then cache the result.
+ QueryPerformanceFrequency(&freq);
- main_scene.scene_buffer->write(&main_scene.meta, renderer.frame_index() * sizeof(main_scene.meta), sizeof(main_scene.meta));
+ BEGIN_MARKER(STARTUP);
+#if ENABLE_RENDERDOC
+ {
+ HMODULE mod = GetModuleHandleA("renderdoc.dll");
+ if (!mod) {
+ // https://github.com/baldurk/renderdoc/issues/1556
+ // If you load one copy of the dll yourself but a different copy of the dll is registered as a vulkan layer then both copies will be loaded because they're loaded from different paths.
+ // They'll be mutually incompatible (you can't use the API fetched from one to capture from another), and other things may break or cause crashes
+ mod = LoadLibraryA("C:/Program Files/RenderDoc/renderdoc.dll");
- // ImDrawData* draw_data = ImGui::GetDrawData();
+ }
- // ui_pass->set_viewport(0.f, 0.f, (float)draw_data->DisplaySize.x, (float)draw_data->DisplaySize.y);
+ if (mod) {
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
+ int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void **)&rdoc_api);
+ assert(ret == 1);
+ (void)ret;
- // auto previous_size = ui_primitives.size();
- // auto commands_count = 0U;
+ rdoc_api->MaskOverlayBits(eRENDERDOC_Overlay_All, eRENDERDOC_Overlay_All);
- // for (int32_t draw_list_index = 0; draw_list_index < draw_data->CmdListsCount; draw_list_index++) {
- // commands_count += draw_data->CmdLists[draw_list_index]->CmdBuffer.size();
- // }
+ RENDERDOC_InputButton key = RENDERDOC_InputButton::eRENDERDOC_Key_F10;
+ rdoc_api->SetCaptureKeys(&key, 1U);
+ }
+ }
+#endif
- // if (ui_primitives.size() < commands_count) {
- // ui_primitives.resize(commands_count);
+ constexpr size_t window_width = 1280U;
+ constexpr size_t window_height = 720U;
+ window wnd { window_width, window_height };
- // 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);
- // }
- // }
+ ImGui::CreateContext();
+ ImGuiIO &io = ImGui::GetIO();
+ io.DisplaySize.x = window_width;
+ io.DisplaySize.y = window_height;
- // 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),
- // };
+ const float aspect_ratio = 16.f / 9.f;
- // 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);
+ point3 position { 13.f, 2.f, -3.f };
+ point3 target {};
+ const float v_fov = 90.f;
+ const float aperture = 0.1f;
+ const float focus_distance = 10.f;
- // for (auto& primitive : ui_primitives) {
- // primitive->set_constant(0, ui_vertex_buffer);
- // }
- // }
+#if VK
+ auto& device = vkdevice::get();
+#else
+ auto& device = dx12::device::get();
+#endif
+ device.init();
- // 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);
+ scene main_scene = scene(camera(position, target, v_fov, aspect_ratio, aperture, focus_distance), window_width, window_height);
- // for (auto& primitive : ui_primitives) {
- // primitive->set_index_buffer(ui_index_buffer);
- // }
- // }
+ handle<device_surface> surface_handle = device.create_surface({
+ .window_handle = wnd.handle,
+#if VK
+ .surface_format = {
+ .format = VK_FORMAT_B8G8R8A8_UNORM,
+ .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ },
+ .present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR,
+ .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
+#else
+ .surface_format = DXGI_FORMAT_R16G16B16A16_FLOAT,
+ .present_mode = DXGI_SWAP_EFFECT_FLIP_DISCARD,
+ .usages = DXGI_USAGE_RENDER_TARGET_OUTPUT,
+#endif
+ .image_count = 2U,
+ });
+ const device_surface& surface = device.get_surface(surface_handle);
- // off_t vertex_buffer_offset = 0;
- // off_t index_buffer_offset = 0;
- // std::vector<VkVertex> vertices;
- // uint32_t draw_call_index = 0;
- // for (int32_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 (int32_t vert_index = 0; vert_index < vertex_buffer.Size; vert_index++) {
- // vertices[vert_index] = *((VkVertex*)&vertex_buffer[vert_index]);
- // }
+ // ==============
+ // create buffers
+ // ==============
+ const handle<device_buffer> staging_buffer_handle = device.create_buffer({
+ .size = 128 * MB,
+#if VK
+ .usages = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+#else
+ .map = true,
+ .states = D3D12_RESOURCE_STATE_COPY_SOURCE,
+ .usages = D3D12_RESOURCE_FLAG_NONE,
+ .heap_type = D3D12_HEAP_TYPE_UPLOAD,
+#endif
+ });
+ const device_buffer& staging_buffer = device.get_buffer(staging_buffer_handle);
- // 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));
+ const handle<device_buffer> vertex_buffer_handle = device.create_buffer({
+ .size = MB * sizeof(uint32_t),
+#if VK
+ .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+#else
+ #endif
+ });
- // 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);
+ const handle<device_buffer> index_buffer_handle = device.create_buffer({
+ .size = MB * sizeof(uint32_t),
+#if VK
+ .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+#else
+#endif
+ });
- // 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
- // );
+ device_buffer vertex_buffer = device.get_buffer(vertex_buffer_handle);
+ device_buffer index_buffer = device.get_buffer(index_buffer_handle);
- // 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++;
- // }
+ // ================
+ // create pipelines
+ // ================
+#if VK
+ size_t code_size = 0U;
+ uint8_t* code = read_file("shaders/test.comp.spv", &code_size);
+ handle<device_pipeline> compute = device.create_compute_pipeline({
+ .cs_code = code,
+ .cs_code_size = code_size,
+ });
- // vertex_buffer_offset += vertex_buffer.Size;
- // index_buffer_offset += index_buffer.Size;
- // }
+ size_t rt_code_size = 0U;
+ uint8_t* rt_code = read_file("shaders/compute.comp.spv", &rt_code_size);
+ handle<device_pipeline> raytracing = device.create_compute_pipeline({
+ .cs_code = rt_code,
+ .cs_code_size = rt_code_size,
+ });
+ size_t tonemapping_code_size = 0U;
+ uint8_t* tonemapping_code = read_file("shaders/tonemapping.comp.spv", &tonemapping_code_size);
+ handle<device_pipeline> tonemapping = device.create_compute_pipeline({
+ .cs_code = tonemapping_code,
+ .cs_code_size = tonemapping_code_size,
+ });
- // ui_pass->set_color_attachment(0, renderer.back_buffer());
+ std::array<VkFormat, 1U> formats { surface.surface_format.format };
+ size_t vertex_code_size = 0U;
+ uint8_t* vertex_code = read_file("shaders/api-test-ui.vert.spv", &vertex_code_size);
+ size_t fragment_code_size = 0U;
+ uint8_t* fragment_code = read_file("shaders/api-test-ui.frag.spv", &fragment_code_size);
+ handle<device_pipeline> graphics = device.create_graphics_pipeline({
+ .vs_code = vertex_code,
+ .vs_code_size = vertex_code_size,
+ .fs_code = fragment_code,
+ .fs_code_size = fragment_code_size,
+ .color_attachments_format = formats
+ });
- renderer.render();
+ size_t transmittance_lut_code_size = 0U;
+ u8* transmittance_lut_code = read_file("shaders/transmittance_lut.comp.spv", &transmittance_lut_code_size);
+ handle<device_pipeline> transmittance_lut_compute = device.create_compute_pipeline({
+ .cs_code = transmittance_lut_code,
+ .cs_code_size = transmittance_lut_code_size,
+ .name = "transmittance_lut_comp",
+ });
+#endif
- main_scene.meta.sample_index++;
-}
+ // ==============
+ // Image loading
+ // ==============
+ int image_width;
+ int image_height;
+ int channels;
+ uint8_t* data = stbi_load("../models/sponza/466164707995436622.jpg", &image_width, &image_height, &channels, 4);
+ size_t size = static_cast<size_t>(image_width) * image_height * 4U;
+ memcpy(staging_buffer.mapped_ptr, data, size);
+ off_t buffer_offset = image_width * image_height * 4;
+ data = stbi_load("../models/sponza/715093869573992647.jpg", &image_width, &image_height, &channels, 4);
+ size = static_cast<size_t>(image_width) * image_height * 4U;
+ auto* addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + buffer_offset);
+ memcpy(addr, data, size);
-#if defined(ENABLE_RENDERDOC)
-RENDERDOC_API_1_1_2 enable_renderdoc() {
- RENDERDOC_API_1_1_2 *rdoc_api = nullptr;
+ u8 *pixels = nullptr;
+ int atlas_width;
+ int atlas_height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &atlas_width, &atlas_height);
-#ifdef WINDOWS
- // At init, on windows
- if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) {
- auto 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);
- }
+ off_t ui_offset = 2L * buffer_offset;
+ size = static_cast<size_t>(atlas_width) * atlas_height * 4U;
+ addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + ui_offset);
+ memcpy(addr, pixels, size);
+
+
+ // ==============
+ // create texures
+ // ==============
+ const handle<device_texture> gpu_texture_handle = device.create_texture({
+ .width = static_cast<uint32_t>(image_width),
+ .height = static_cast<uint32_t>(image_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ .format = VK_FORMAT_R8G8B8A8_UNORM,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .states = D3D12_RESOURCE_STATE_COPY_DEST,
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
#endif
+ });
- return rdoc_api;
-}
+ const handle<device_texture> second_texture = device.create_texture({
+ .width = static_cast<uint32_t>(image_width),
+ .height = static_cast<uint32_t>(image_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
+ .format = VK_FORMAT_R8G8B8A8_UNORM,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .states = D3D12_RESOURCE_STATE_COPY_DEST,
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
#endif
+ });
-int main() {
+ const handle<device_texture> output_texture_handle = device.create_texture({
+ .width = static_cast<uint32_t>(image_width),
+ .height = static_cast<uint32_t>(image_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_STORAGE_BIT,
+ .format = VK_FORMAT_R8G8B8A8_UNORM,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
+#endif
+ });
+
+ const handle<device_texture> ui_texture_handle = device.create_texture({
+ .width = static_cast<uint32_t>(atlas_width),
+ .height = static_cast<uint32_t>(atlas_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ .format = VK_FORMAT_R8G8B8A8_UNORM,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .states = D3D12_RESOURCE_STATE_COPY_DEST,
+ .usages = D3D12_RESOURCE_FLAG_NONE,
+ .format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
+#endif
+ .name = "glyph atlas"
+ });
-#if defined(ENABLE_RENDERDOC)
- auto* rdoc_api = enable_renderdoc();
+ const handle<device_texture> acc_handle = device.create_texture({
+ .width = static_cast<uint32_t>(window_width),
+ .height = static_cast<uint32_t>(window_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R32G32B32A32_FLOAT,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
#endif
+ .name = "accumulation texture"
+ });
- const float aspect_ratio = 16.0 / 9.0;
- const auto width = 400;
- auto height = (uint32_t)(width / aspect_ratio);
+ const handle<device_texture> result_handle = device.create_texture({
+ .width = static_cast<uint32_t>(window_width),
+ .height = static_cast<uint32_t>(window_height),
+#if VK
+ .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
+ .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R32G32B32A32_FLOAT,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
+#endif
+ .name = "output texture"
+ });
- window wnd { width, height };
+ const handle<device_texture> transmittance_lut_handle = device.create_texture({
+ .width = static_cast<uint32_t>(1024),
+ .height = static_cast<uint32_t>(1024),
+#if VK
+ .usages = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ .format = VK_FORMAT_R16G16B16A16_SFLOAT,
+ .type = VK_IMAGE_TYPE_2D,
+#else
+ .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS,
+ .format = DXGI_FORMAT_R8G8B8A8_UNORM,
+ .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
+#endif
+ .name = "transmittance_lut",
+ });
- 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();
+#if VK
+ u32 acc_storage_index = device.get_texture(acc_handle).get_storage_index();
+ u32 result_storage_index = device.get_texture(result_handle).get_storage_index();
+#endif
- point3 position { 13.f, 2.f, -3.f };
- point3 target {};
- const auto v_fov = 90.f;
- const auto aperture = 0.1f;
- const auto focus_distance = 10.f;
+ const device_texture& ui_texture = device.get_texture(ui_texture_handle);
+ const device_texture& transmittance_lut = device.get_texture(transmittance_lut_handle);
+ debug_texture_list.push_back(transmittance_lut_handle);
- vkrenderer renderer { wnd };
+ io.Fonts->SetTexID(reinterpret_cast<void*>(static_cast<uintptr_t>(ui_texture.get_sampled_index())));
- ImGui::CreateContext();
- ImGuiIO &io = ImGui::GetIO();
- io.DisplaySize.x = (float)width;
- io.DisplaySize.y = (float)height;
- auto main_scene = scene(camera(position, target, v_fov, aspect_ratio, aperture, focus_distance), width, height);
+#if VK
+ std::array<graphics_command_buffer, 4U> graphics_command_buffers;
+ device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), QueueType::GRAPHICS, "graphics_cmd_buf");
+#else
+ std::array<dx12::graphics_command_buffer, 4U> graphics_command_buffers;
+ device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), dx12::QueueType::GRAPHICS);
+#endif
- auto *raytracing_pass = renderer.create_compute_renderpass();
- raytracing_pass->set_pipeline("compute");
- watcher::watch_file(std::filesystem::path("../shaders/compute.comp"), [&]() {
- LPCSTR app_name = "glslc.exe --target-env=vulkan1.2 -std=460 ../shaders/compute.comp -o shaders/compute.comp.spv -I \"../shaders/include\"\0";
- STARTUPINFO start_info {};
- PROCESS_INFORMATION proc_info {};
- if (FAILED(CreateProcessA(
- app_name,
- nullptr,
- nullptr,
- nullptr,
- FALSE,
- 0,
- nullptr,
- nullptr,
- &start_info,
- &proc_info
- )))
- log_last_error();
- WaitForSingleObject(proc_info.hProcess, INFINITE);
- CloseHandle(proc_info.hProcess);
- CloseHandle(proc_info.hThread);
+ // =============
+ // API test code
+ // =============
+ RD_START_CAPTURE;
+ graphics_command_buffers[0].start();
+
+#if VK
+ graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ graphics_command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+#endif
+
+ graphics_command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle);
+ graphics_command_buffers[0].copy(staging_buffer_handle, second_texture, buffer_offset);
+ graphics_command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, ui_offset);
+#if VK
+ graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
+ graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- raytracing_pass->set_pipeline("compute");
- });
- auto *accumulation_texture = vkrenderer::create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
- auto *output_texture = vkrenderer::create_2d_texture(width, height, VK_FORMAT_R32G32B32A32_SFLOAT);
- raytracing_pass->set_constant(0, main_scene.scene_buffer);
- 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);
- raytracing_pass->set_constant(32, main_scene.normals_buffer);
- raytracing_pass->set_constant(40, main_scene.uvs_buffer);
- raytracing_pass->set_constant(48, main_scene.materials_buffer);
- raytracing_pass->set_dispatch_size(width / 8 + 1, height / 8 + 1, 1);
+ {
+ device_buffer& draws_uniform_buffer = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW);
+ {
+ struct params {
+ u32 input1;
+ u32 input2;
+ u32 output;
+ u32 pad;
+ } *params = draws_uniform_buffer.allocate<struct params>();
+ params->input1 = device.get_texture(second_texture).get_storage_index();
+ params->input2 = device.get_texture(gpu_texture_handle).get_storage_index();
+ params->output = device.get_texture(output_texture_handle).get_storage_index();
- // 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);
+ graphics_command_buffers[0].dispatch({
+ .pipeline = compute,
+ .group_size = { .vec = { static_cast<u32>(image_width), static_cast<u32>(image_height), 1U }},
+ .local_group_size = { .vec = { 8U, 8U, 1U }},
+ });
+ }
- // renderer.update_image(ui_texture, pixels);
- // auto ui_texture_sampler = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
+ {
+ struct params {
+ u32 lut_id;
+ u32 width;
+ u32 height;
+ u32 pad;
+ } *params = draws_uniform_buffer.allocate<struct params>();
+ params->lut_id = transmittance_lut.get_storage_index();
+ params->width = transmittance_lut.width;
+ params->height = transmittance_lut.height;
- // Buffer* ui_vertex_buffer = nullptr;
- // Buffer* ui_index_buffer = nullptr;
+ graphics_command_buffers[0].dispatch({
+ .pipeline = transmittance_lut_compute,
+ .group_size = { .vec = { 1024U, 1024U, 1U }},
+ .local_group_size = { .vec { 8U, 8U, 1U }},
+ });
+ }
+ }
- // const char* 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();
+ graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+#endif
- auto can_render = true;
+ graphics_command_buffers[0].stop();
- while (wnd.isOpen) {
- end = std::chrono::high_resolution_clock::now();
+ device.submit(graphics_command_buffers.data(), 1);
+ device.wait();
- delta_time = std::chrono::duration<float, std::milli>(end - start).count();
+ RD_END_CAPTURE;
- start = std::chrono::high_resolution_clock::now();
+ END_MARKER(STARTUP);
- io.DeltaTime = delta_time;
+ watch_file("../shaders/compute.comp", watch_func);
- watcher::pull_changes();
+#if VK
+ std::array<handle<device_texture>, 1U> color_attachment {};
+ constexpr uint32_t virtual_frames_count = 2U;
+ float delta = 0.f; // milliseconds
+ u32 speed = 1U;
+ uint32_t frame_count = 0U;
+ while(wnd.isOpen) {
+ vec3 dir = { 0.f, 0.f, 0.f };
+ float rot = 0.f;
+ LARGE_INTEGER start_qpc;
+ QueryPerformanceCounter(&start_qpc);
wnd.poll_events();
- for (auto &event : wnd.events) {
- switch (event.type) {
- case EVENT_TYPES::RESIZE: {
- main_scene.meta.width = event.width;
- main_scene.meta.height = event.height;
+ pull_changes();
- io.DisplaySize.x = (float)event.width;
- io.DisplaySize.y = (float)event.height;
+ uint32_t virtual_frame_index = frame_count % virtual_frames_count;
+ auto command_buffer = graphics_command_buffers[2U + virtual_frame_index];
- if (event.width == 0 && event.height == 0) {
- can_render = false;
- } else {
- can_render = true;
- renderer.recreate_swapchain();
- main_scene.meta.cam.set_aspect_ratio((float)event.width / (float)event.height);
+ main_scene.meta.sample_index++;
- delete accumulation_texture;
- delete output_texture);
- accumulation_texture = vkrenderer::create_2d_texture(event.width, event.height, VK_FORMAT_R32G32B32A32_SFLOAT);
- output_texture = vkrenderer::create_2d_texture(event.width, event.height, VK_FORMAT_R32G32B32A32_SFLOAT);
- raytracing_pass->set_dispatch_size(event.width / 8 + 1, event.height / 8 + 1, 1);
+ //
+ // IOs
+ //
+ {
+ io.AddMouseButtonEvent(BUTTON::LEFT, wnd.mouse[BUTTON::LEFT]);
+ io.AddMouseButtonEvent(BUTTON::RIGHT, wnd.mouse[BUTTON::LEFT]);
+ io.AddMouseButtonEvent(BUTTON::MIDDLE, wnd.mouse[BUTTON::LEFT]);
+ for (event& event : wnd.events) {
+ if (event.type == EVENT_TYPE::MOUSE_MOVE) {
+ io.AddMousePosEvent(static_cast<float>(event.data.position.x), static_cast<float>(event.data.position.y));
+ } else if (event.type == EVENT_TYPE::MOUSE_WHEEL) {
+ io.AddMouseWheelEvent(static_cast<float>(event.data.delta.x), static_cast<float>(event.data.delta.y));
}
- main_scene.meta.sample_index = 1;
+ if (event.type == EVENT_TYPE::KEY_PRESS) {
+ if (event.data.key == KEY::F2) {
+#if ENABLE_RENDERDOC
+ if (!rdoc_api->IsTargetControlConnected()) {
+ rdoc_api->LaunchReplayUI(true, nullptr);
+ }
+#endif
+ }
+ }
- break;
+ if (event.type == EVENT_TYPE::KEY_DOWN) {
+ if (event.data.key == KEY::W) {
+ dir += main_scene.meta.cam.forward;
+ }
+ if (event.data.key == KEY::A) {
+ dir += -main_scene.meta.cam.right;
+ }
+ if (event.data.key == KEY::S) {
+ dir += -main_scene.meta.cam.forward;
+ }
+ if (event.data.key == KEY::D) {
+ dir += main_scene.meta.cam.right;
+ }
+ if (event.data.key == KEY::SPACE) {
+ dir += vec3 { 0.f, 1.f, 0.f };
+ }
+ if (event.data.key == KEY::LCTRL) {
+ dir += vec3 { 0.f, -1.f, 0.f };
+ }
+ if (event.data.key == KEY::E) {
+ rot += 0.001f;
+ }
+ if (event.data.key == KEY::Q) {
+ rot += -0.001f;
+ }
+ if (event.data.key == KEY::PAGE_UP) {
+ speed++;
+ }
+ if (event.data.key == KEY::PAGE_DOWN) {
+ if (speed > 1U) {
+ speed--;
+ }
+ }
+
+ }
}
- case EVENT_TYPES::KEY_PRESS: {
- auto move_speed = 1.f * delta_time;
- if (wnd.keyboard[KEYS::LSHIFT] || wnd.keyboard[KEYS::RSHIFT]) { move_speed *= 10.f; }
+ }
- vec3 move_vec{};
+ if (!dir.is_zero()) {
+ main_scene.meta.cam.move(dir.normalize() * delta * static_cast<float>(speed));
+ main_scene.meta.sample_index = 1U;
+ }
+ if (rot != 0.f) {
+ main_scene.meta.cam.rotate_y(rot * delta * static_cast<float>(speed));
+ main_scene.meta.sample_index = 1U;
+ }
- switch (event.key) {
- case KEYS::W: {
- move_vec = main_scene.meta.cam.forward * move_speed;
- break;
- }
+ ui(&main_scene, delta);
- case KEYS::S: {
- move_vec = -main_scene.meta.cam.forward * move_speed;
- break;
- }
- case KEYS::D: {
- move_vec = main_scene.meta.cam.right * move_speed;
- break;
- }
- case KEYS::A: {
- move_vec = -main_scene.meta.cam.right * move_speed;
- break;
- }
- case KEYS::E: {
- main_scene.meta.cam.rotate_y(0.001f * delta_time);
- main_scene.meta.sample_index = 1;
- break;
- }
- case KEYS::Q: {
- main_scene.meta.cam.rotate_y(-0.001f * delta_time);
- main_scene.meta.sample_index = 1;
- break;
- }
- case KEYS::SPACE: {
- move_vec = main_scene.meta.cam.up * move_speed;
- break;
- }
- case KEYS::LCTRL: {
- move_vec = -main_scene.meta.cam.up * move_speed;
- break;
- }
- default:
- break;
- }
+ ImGuiMouseCursor cursor_style = ImGui::GetMouseCursor();
+ window::set_cursor(static_cast<CURSOR_TYPE>(cursor_style));
- main_scene.meta.cam.move(move_vec);
+ // ==================
+ // copy ImGui buffers
+ // ==================
+ const ImDrawData* draw_data = ImGui::GetDrawData();
+ {
+ u32 vertex_offset = 0;
+ u32 index_offset = 0;
+ for (s32 index = 0U; index < draw_data->CmdListsCount; index++) {
+ ImDrawList* cmd_list = draw_data->CmdLists[index];
- if (!move_vec.near_zero()) { main_scene.meta.sample_index = 1; }
+ size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size();
+ u8* vtx_ptr = static_cast<uint8_t*>(vertex_buffer.mapped_ptr) + vertex_offset;
+ memcpy(vtx_ptr, cmd_list->VtxBuffer.Data, vertex_bytes_size);
+ vertex_offset += static_cast<off_t>(vertex_bytes_size);
- break;
- }
- case EVENT_TYPES::BUTTON_PRESS: {
- if (event.button == BUTTONS::LEFT) { io.MouseDown[0] = true; }
- if (event.button == BUTTONS::RIGHT) { io.MouseDown[1] = true; }
- break;
+ size_t index_bytes_size = sizeof(ImDrawIdx) * cmd_list->IdxBuffer.size();
+ memcpy(static_cast<uint8_t*>(index_buffer.mapped_ptr) + index_offset, cmd_list->IdxBuffer.Data, index_bytes_size);
+ index_offset += static_cast<off_t>(index_bytes_size);
}
- case EVENT_TYPES::BUTTON_RELEASE: {
- if (event.button == BUTTONS::LEFT) { io.MouseDown[0] = false; }
- if (event.button == BUTTONS::RIGHT) { io.MouseDown[1] = false; }
- break;
+ }
+
+ // ======================
+ // global uniforms update
+ // ======================
+ {
+ metadata * const globals = vkdevice::get().get_bindingmodel().get_uniform_buffer(UniformTypes::GLOBAL).allocate<metadata>();
+ memcpy(static_cast<void*>(globals), &main_scene.meta, sizeof(main_scene.meta));
+ }
+
+ // TODO: Refactor backbuffer acquisition
+ auto backbuffer = surface.swapchain_images[device.acquire_image_index(surface_handle)];
+ color_attachment[0] = backbuffer;
+
+ // RD_START_CAPTURE;
+ command_buffer.start();
+
+ command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
+
+ {
+ if (virtual_frame_index == 0) {
+ command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
+ command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL);
+ } else {
+ command_buffer.barrier(result_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL);
+ command_buffer.barrier(acc_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
}
- case EVENT_TYPES::MOUSE_MOVE: {
- io.MousePos = ImVec2{(float)event.x, (float)event.y};
- break;
+
+ {
+ struct params {
+ uintptr_t bvh_buffer;
+ uintptr_t indices_buffer;
+ uintptr_t positions_buffer;
+ uintptr_t normals_buffer;
+ uintptr_t uvs_buffer;
+ uintptr_t materials_buffer;
+ u32 output_id;
+ u32 accumulation_id;
+ };
+ struct params* uniforms = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW).allocate<params>();
+ uniforms->bvh_buffer = main_scene.bvh_buffer_address();
+ uniforms->indices_buffer = main_scene.indices_buffer_address();
+ uniforms->positions_buffer = main_scene.positions_buffer_address();
+ uniforms->normals_buffer = main_scene.normals_buffer_address();
+ uniforms->uvs_buffer = main_scene.uvs_buffer_address();
+ uniforms->materials_buffer = main_scene.materials_buffer_address();
+ uniforms->output_id = (virtual_frame_index == 0U) ? result_storage_index : acc_storage_index;
+ uniforms->accumulation_id = (virtual_frame_index == 0U) ? acc_storage_index : result_storage_index;
+
+ command_buffer.dispatch({
+ .pipeline = raytracing,
+ .group_size = { .vec { window_width / main_scene.meta.downscale_factor, window_height / main_scene.meta.downscale_factor, 1U, } },
+ .local_group_size = { .vec { 8U, 8U, 1U, } },
+ });
}
- default:
- break;
+
+ {
+ struct params {
+ u32 output_id;
+ u32 accumulation_id;
+ } *uniforms = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW).allocate<params>();
+ // TODO: Refactor backbuffer acquisition
+ uniforms->output_id = device.get_texture(backbuffer).get_storage_index();
+ uniforms->accumulation_id = (virtual_frame_index == 0U) ? result_storage_index : acc_storage_index;
+
+ command_buffer.dispatch({
+ .pipeline = tonemapping,
+ .group_size = { .vec { window_width / main_scene.meta.downscale_factor, window_height / main_scene.meta.downscale_factor, 1U, } },
+ .local_group_size = { .vec { 8U, 8U, 1U, } },
+ });
}
}
- wnd.events.clear();
+ command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- raytracing_pass->set_ouput_texture(output_texture);
- raytracing_pass->set_constant(60, accumulation_texture);
+ command_buffer.begin_renderpass({
+ .render_area = {
+ .x = static_cast<int32_t>(draw_data->DisplayPos.x),
+ .y = static_cast<int32_t>(draw_data->DisplayPos.y),
+ .width = static_cast<uint32_t>(draw_data->DisplaySize.x),
+ .height = static_cast<uint32_t>(draw_data->DisplaySize.y),
+ },
+ .color_attachments = color_attachment,
+ });
- renderer.begin_frame();
+ auto& draws_uniform_buffer = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW);
+ uint32_t vertex_offset = 0;
+ uint32_t index_offset = 0;
+ for (s32 index = 0U ; index < draw_data->CmdListsCount; index++) {
+ auto* cmd_list = draw_data->CmdLists[index];
- // update_ui(main_scene, delta_time);
-
- if (can_render) {
- render(main_scene, renderer);
+ for (auto& draw_command : cmd_list->CmdBuffer) {
+ ImTextureID texture_id = draw_command.TexRef.GetTexID();
+ {
+ struct ui_params {
+ u64 vertex_buffer;
+ float scale[2U];
+ float translate[2U];
+ uint32_t texture_index;
+ u32 padding;
+ };
+ struct ui_params* ui_param = draws_uniform_buffer.allocate<ui_params>();
+ *ui_param = ui_params{
+ .vertex_buffer = vertex_buffer.device_address,
+ .scale {
+ 2.f / draw_data->DisplaySize.x,
+ 2.f / draw_data->DisplaySize.y,
+ },
+ .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),
+ },
+ .texture_index = *reinterpret_cast<uint32_t*>(&texture_id),
+ };
+ }
- std::swap(output_texture, accumulation_texture);
+ command_buffer.draw_indexed({
+ .pipeline = graphics,
+ .index_buffer = index_buffer_handle,
+ .vertex_count = draw_command.ElemCount,
+ .vertex_offset = draw_command.VtxOffset + vertex_offset,
+ .index_offset = draw_command.IdxOffset + index_offset,
+ .instance_count = 1U,
+ });
+ }
+ vertex_offset += cmd_list->VtxBuffer.size();
+ index_offset += cmd_list->IdxBuffer.size();
}
- renderer.finish_frame();
+ command_buffer.end_renderpass();
+ command_buffer.barrier(backbuffer, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+
+ command_buffer.stop();
+
+ device.submit_before_present(surface_handle, &command_buffer, 1U);
+ device.present(surface_handle);
+ // device.wait();
+ LARGE_INTEGER end_qpc;
+ QueryPerformanceCounter(&end_qpc);
+ LONGLONG diff_qpc = end_qpc.QuadPart - start_qpc.QuadPart;
+ delta = static_cast<float>(diff_qpc * 1000LL) / freq.QuadPart;
frame_count++;
+
+ // RD_END_CAPTURE;
}
- //-------------------------
- // Image exporter
- //-------------------------
- // PPM format header
- // std::cout << "P3\n" << width << '\n' << height << "\n255" << std::endl;
- // auto output_image = renderer.output_image();
- // for (size_t index = 0; index < height * width; index++) {
- // write_color(std::cout, output_image[index]);
- // }
+ device.wait();
+
+ main_scene.deinit();
+
+ device.destroy_surface(surface_handle);
+
+ device.destroy_pipeline(compute);
+ device.destroy_pipeline(graphics);
+ device.destroy_pipeline(raytracing);
+ device.destroy_pipeline(tonemapping);
+
+ device.destroy_pipeline(transmittance_lut_compute);
+ device.destroy_texture(transmittance_lut_handle);
+
+ device.destroy_texture(gpu_texture_handle);
+ device.destroy_texture(second_texture);
+ device.destroy_texture(output_texture_handle);
+ device.destroy_texture(ui_texture_handle);
+ device.destroy_texture(acc_handle);
+ device.destroy_texture(result_handle);
+
+ device.destroy_buffer(staging_buffer_handle);
+ device.destroy_buffer(vertex_buffer_handle);
+ device.destroy_buffer(index_buffer_handle);
+ device.deinit();
- // std::cerr << "Done !" << std::endl;
+ ImGui::DestroyContext();
+#endif // VK
return 0;
}
diff --git a/src/primitive-renderpass.cpp b/src/primitive-renderpass.cpp
deleted file mode 100644
index 45d48e8..0000000
--- a/src/primitive-renderpass.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "primitive-renderpass.hpp"
-
-#include "vulkan-loader.hpp"
-
-
-Primitive::Primitive(PrimitiveRenderpass& render_pass)
- : api(vkrenderer::api), primitive_render_pass(render_pass)
- {};
-
-void Primitive::set_pipeline(const char* shader_name) {
- std::vector<VkDynamicState> dynamic_states {
- VK_DYNAMIC_STATE_VIEWPORT,
- VK_DYNAMIC_STATE_SCISSOR
- };
-
- pipeline = api.create_graphics_pipeline(shader_name, (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 + offset, constant, sizeof(uint64_t));
-}
-
-void Primitive::set_constant(off_t offset, Texture* texture) {
- const auto& image = api.get_image(texture->device_image);
-
- memcpy(constants + offset, (void*)&image.bindless_storage_index, sizeof(bindless_index));
-}
-
-void Primitive::set_constant(off_t offset, Buffer* buffer) {
- const auto& device_buffer = api.get_buffer(buffer->device_buffer);
- memcpy(constants + offset, (void*)&device_buffer.device_address, sizeof(VkDeviceAddress));
-}
-
-void Primitive::set_constant(off_t offset, Sampler* sampler) {
- const auto& device_sampler = api.get_sampler(sampler->device_sampler);
- memcpy(constants + offset, (void*)&device_sampler.bindless_index, sizeof(bindless_index));
-}
-
-void Primitive::set_index_buffer(Buffer* buffer) {
- this->index_buffer = 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 indices_off, off_t vertex_off) {
- this->element_count = vertex_count;
- this->indices_offset = indices_off;
- this->vertex_offset = vertex_off;
-}
-
-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,
- indices_offset,
- 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) {
- const 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/vk-api.cpp b/src/vk-api.cpp
deleted file mode 100644
index 2040b44..0000000
--- a/src/vk-api.cpp
+++ /dev/null
@@ -1,1257 +0,0 @@
-#include "vk-api.hpp"
-
-#include <cassert>
-#include <filesystem>
-
-#include <vk_mem_alloc.h>
-
-#include "utils.hpp"
-#include "vk-context.hpp"
-#include "window.hpp"
-
-#include "vulkan-loader.hpp"
-
-#ifdef _DEBUG
-#define VKRESULT(result) assert(result == VK_SUCCESS);
-#else
-#define VKRESULT(result) result;
-#endif
-
-
-vkapi::vkapi(vkcontext& context)
- : context(context) {
- VkDescriptorPoolSize descriptor_pools_sizes[] = {
- {
- .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .descriptorCount = (uint32_t)global_descriptor::pool_size,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
- .descriptorCount = (uint32_t)global_descriptor::pool_size,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .descriptorCount = (uint32_t)global_descriptor::pool_size,
- },
- {
- .type = VK_DESCRIPTOR_TYPE_SAMPLER,
- .descriptorCount = (uint32_t)global_descriptor::pool_size,
- }
- };
-
- VkDescriptorPoolCreateInfo descriptor_pool_create_info = {};
- descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
- descriptor_pool_create_info.pNext = nullptr;
- descriptor_pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
- descriptor_pool_create_info.maxSets = 0xff;
- descriptor_pool_create_info.poolSizeCount = sizeof(descriptor_pools_sizes) / sizeof(descriptor_pools_sizes[0]);
- descriptor_pool_create_info.pPoolSizes = descriptor_pools_sizes;
-
- VKRESULT(vkCreateDescriptorPool(context.device, &descriptor_pool_create_info, nullptr, &descriptor_pool))
-
- // Global descriptor
- VkDescriptorSetLayoutBinding bindless_layout_bindings[] = {
- {
- .binding = 0,
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
- .descriptorCount = global_descriptor::pool_size,
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
- },
- {
- .binding = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
- .descriptorCount = global_descriptor::pool_size,
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
- },
- {
- .binding = 2,
- .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
- .descriptorCount = global_descriptor::pool_size,
- .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
- },
- };
-
- VkDescriptorBindingFlags flags[3] = {
- VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
- };
-
- VkDescriptorSetLayoutBindingFlagsCreateInfo descriptor_set_layout_binding_flags = {};
- descriptor_set_layout_binding_flags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
- descriptor_set_layout_binding_flags.pNext = VK_NULL_HANDLE;
- descriptor_set_layout_binding_flags.bindingCount = sizeof(flags) / sizeof(VkDescriptorBindingFlags);
- descriptor_set_layout_binding_flags.pBindingFlags = flags;
-
- VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = {};
- descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- descriptor_set_layout_create_info.pNext = &descriptor_set_layout_binding_flags;
- descriptor_set_layout_create_info.flags = 0;
- descriptor_set_layout_create_info.bindingCount = sizeof(bindless_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding);
- descriptor_set_layout_create_info.pBindings = bindless_layout_bindings;
-
- VKRESULT(vkCreateDescriptorSetLayout(context.device, &descriptor_set_layout_create_info, nullptr, &bindless_descriptor.set_layout))
-
-
- VkPushConstantRange push_constants[] = {
- {
- .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
- .offset = 0,
- .size = 64,
- },
- {
- .stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS,
- .offset = 64,
- .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 = {};
- layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- layout_create_info.pNext = nullptr;
- layout_create_info.flags = 0;
- layout_create_info.setLayoutCount = 1;
- layout_create_info.pSetLayouts = &bindless_descriptor.set_layout;
- layout_create_info.pushConstantRangeCount = sizeof(push_constants) / sizeof(VkPushConstantRange);
- layout_create_info.pPushConstantRanges = push_constants;
-
- VKRESULT(vkCreatePipelineLayout(context.device, &layout_create_info, nullptr, &bindless_descriptor.pipeline_layout))
-
-
- VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {};
- descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- descriptor_set_allocate_info.pNext = VK_NULL_HANDLE;
- descriptor_set_allocate_info.descriptorPool = descriptor_pool;
- descriptor_set_allocate_info.descriptorSetCount = 1;
- descriptor_set_allocate_info.pSetLayouts = &bindless_descriptor.set_layout;
-
- vkAllocateDescriptorSets(context.device, &descriptor_set_allocate_info, &bindless_descriptor.set);
-}
-
-vkapi::~vkapi() {
- // Free resources
- for (handle buffer_handle = 0; buffer_handle < buffers.size(); buffer_handle++) {
- destroy_buffer(buffer_handle);
- }
-
- for (handle image_handle = 0; image_handle < images.size(); image_handle++) {
- destroy_image(image_handle);
- }
-
- 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);
- vkDestroyPipelineLayout(context.device, bindless_descriptor.pipeline_layout, nullptr);
- vkFreeDescriptorSets(context.device, descriptor_pool, 1, &bindless_descriptor.set);
-
- vkDestroyDescriptorPool(context.device, descriptor_pool, nullptr);
-}
-
-handle vkapi::create_buffer(size_t data_size, VkBufferUsageFlags buffer_usage, uint32_t mem_usage) {
- auto* buffer = new struct buffer();
-
- VkBufferCreateInfo buffer_info = {};
- buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buffer_info.size = data_size;
- buffer_info.usage = buffer_usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR;
-
- VmaAllocationCreateInfo alloc_create_info = {};
- alloc_create_info.usage = (VmaMemoryUsage)mem_usage;
- alloc_create_info.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
-
- VmaAllocationInfo alloc_info{};
-
- VKRESULT(vmaCreateBuffer(context.allocator, &buffer_info, &alloc_create_info, &buffer->handle, &buffer->alloc, &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->size = data_size;
-
- buffer->device_address = vkGetBufferDeviceAddress(context.device, &buffer_device_address_info);
- buffer->device_ptr = alloc_info.pMappedData;
-
- buffers.push_back(buffer);
-
- return buffers.size() - 1;
-}
-
-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, buffers[src]->handle, buffers[dst]->handle, 1, &buffer_copy);
-}
-
-// TODO: Change handle type, here we don't know what type of ressources we are working with
-void vkapi::copy_buffer(VkCommandBuffer cmd_buf, handle src, handle dst, size_t size, size_t buffer_offset) {
- auto& dst_image = images[dst];
-
- VkImageSubresourceLayers image_subresource_layers = {};
- image_subresource_layers.aspectMask = dst_image->subresource_range.aspectMask;
- image_subresource_layers.mipLevel = 0;
- image_subresource_layers.baseArrayLayer = 0;
- image_subresource_layers.layerCount = 1;
-
- VkBufferImageCopy buffer_to_image_copy = {};
- buffer_to_image_copy.bufferOffset = buffer_offset;
- buffer_to_image_copy.bufferRowLength = 0;
- 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_image->size;
-
- vkCmdCopyBufferToImage(cmd_buf, buffers[src]->handle, dst_image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_to_image_copy);
-}
-
-void vkapi::destroy_buffer(handle buffer) {
- vmaDestroyBuffer(context.allocator, buffers[buffer]->handle, buffers[buffer]->alloc);
-
- // TODO: Free the element once using freelists
- // buffers.erase(buffer.handle);
-}
-
-handle vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags usages) {
- auto* image = new struct image();
-
- 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;
-
- VkImageCreateInfo img_create_info = {};
- img_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- img_create_info.pNext = VK_NULL_HANDLE;
- img_create_info.flags = 0;
- img_create_info.imageType = VK_IMAGE_TYPE_2D;
- img_create_info.format = format;
- img_create_info.extent = size;
- img_create_info.mipLevels = 1;
- img_create_info.arrayLayers = 1;
- img_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
- img_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
- img_create_info.usage = usages;
- img_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- img_create_info.queueFamilyIndexCount = 0;
- img_create_info.pQueueFamilyIndices = nullptr;
- img_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-
- VmaAllocationCreateInfo alloc_create_info = {};
- alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-
- VmaAllocationInfo alloc_info{};
-
- VKRESULT(vmaCreateImage(context.allocator, &img_create_info, &alloc_create_info, &image->handle, &image->alloc, &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.viewType = VK_IMAGE_VIEW_TYPE_2D;
- image_view_create_info.format = format;
- image_view_create_info.components = {
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY
- };
- image_view_create_info.subresourceRange = image->subresource_range;
-
- VKRESULT(vkCreateImageView(context.device, &image_view_create_info, VK_NULL_HANDLE, &image->view))
-
- image->format = format;
- image->usages = usages;
-
- images.push_back(image);
-
- auto image_handle = images.size() - 1;
-
- if ((usages & VK_IMAGE_USAGE_STORAGE_BIT) != 0U) {
- 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) != 0U) {
- 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(handle image) {
- auto* current_image = images[image];
-
- if (current_image->bindless_storage_index != 0U) {
- bindless_descriptor.free(current_image->bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- }
-
- if (current_image->bindless_sampled_index != 0U) {
- bindless_descriptor.free(current_image->bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
- }
-
- vmaDestroyImage(context.allocator, current_image->handle, current_image->alloc);
- vkDestroyImageView(context.device, current_image->view, nullptr);
-
- // TODO: Free once using freelist
- // images.erase(image.handle);
-}
-
-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_handles[image_index] = create_image(size, format, usages);
- }
-
- return images_handles;
-}
-
-void vkapi::destroy_images(std::vector<handle>& imgs) {
- for (auto handle : imgs) {
- destroy_image(handle);
- }
-}
-
-VkFence vkapi::create_fence() const {
- VkFence fence;
- VkFenceCreateInfo create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- create_info.pNext = nullptr;
- create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- VKRESULT(vkCreateFence(context.device, &create_info, nullptr, &fence))
-
- return fence;
-}
-
-void vkapi::destroy_fence(VkFence fence) const {
- vkDestroyFence(context.device, fence, nullptr);
-}
-
-std::vector<VkFence> vkapi::create_fences(size_t fences_count) const {
- std::vector<VkFence> fences{ fences_count };
-
- for (size_t fence_index = 0; fence_index < fences_count; fence_index++) {
- fences[fence_index] = create_fence();
- }
-
- return fences;
-}
-
-void vkapi::destroy_fences(VkFence fences[], size_t fences_count) const {
- for (size_t index{ 0 }; index < fences_count; index++) {
- vkDestroyFence(context.device, fences[index], nullptr);
- }
-}
-
-VkSemaphore vkapi::create_semaphore() const {
- VkSemaphore semaphore;
- VkSemaphoreCreateInfo create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- create_info.pNext = nullptr;
- create_info.flags = 0;
-
- VKRESULT(vkCreateSemaphore(context.device, &create_info, nullptr, &semaphore))
-
- return semaphore;
-}
-
-void vkapi::destroy_semaphore(VkSemaphore semaphore) const {
- vkDestroySemaphore(context.device, semaphore, nullptr);
-}
-
-std::vector<VkSemaphore> vkapi::create_semaphores(size_t semaphores_count) const {
- std::vector<VkSemaphore> semaphores{ semaphores_count };
-
- for (size_t semaphore_index{ 0 }; semaphore_index < semaphores_count; semaphore_index++) {
- semaphores[semaphore_index] = create_semaphore();
- }
-
- return semaphores;
-}
-
-void vkapi::destroy_semaphores(VkSemaphore semaphores[], size_t semaphores_count) const {
- for (size_t index{ 0 }; index < semaphores_count; index++) {
- vkDestroySemaphore(context.device, semaphores[index], nullptr);
- }
-}
-
-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;
- sampler_create_info.flags = 0;
- sampler_create_info.magFilter = filter;
- sampler_create_info.minFilter = filter;
- sampler_create_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
- sampler_create_info.addressModeU = address_mode;
- sampler_create_info.addressModeV = address_mode;
- sampler_create_info.addressModeW = address_mode;
- sampler_create_info.mipLodBias = 0.f;
- sampler_create_info.anisotropyEnable = VK_FALSE;
- sampler_create_info.compareEnable = VK_FALSE;
- sampler_create_info.compareOp = VK_COMPARE_OP_ALWAYS;
- sampler_create_info.minLod = 0.f;
- sampler_create_info.maxLod = 0.f;
- sampler_create_info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
- sampler_create_info.unnormalizedCoordinates = VK_FALSE;
-
- 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);
-
-
- samplers.push_back(sampler);
-
- update_descriptor_sampler(samplers.size() - 1);
-
- return samplers.size() - 1;
-}
-
-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, current_sampler->handle, VK_NULL_HANDLE);
-
- // samplers.erase(sampler.handle);
-}
-
-VkCommandPool vkapi::create_command_pool() const {
- VkCommandPoolCreateInfo cmd_pool_create_info = {};
- cmd_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- cmd_pool_create_info.pNext = nullptr;
- cmd_pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- cmd_pool_create_info.queueFamilyIndex = context.graphics_queue.index;
-
- VkCommandPool command_pool;
- VKRESULT(vkCreateCommandPool(context.device, &cmd_pool_create_info, nullptr, &command_pool))
-
- return command_pool;
-}
-
-void vkapi::allocate_command_buffers(VkCommandPool command_pool, VkCommandBuffer* command_buffers, size_t count) const {
- VkCommandBufferAllocateInfo cmd_buf_allocate_info = {};
- cmd_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- cmd_buf_allocate_info.pNext = VK_NULL_HANDLE;
- cmd_buf_allocate_info.commandPool = command_pool;
- cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- cmd_buf_allocate_info.commandBufferCount = count;
-
- vkAllocateCommandBuffers(context.device, &cmd_buf_allocate_info, command_buffers);
-}
-
-// TODO: attachment structure
-VkRenderPass vkapi::create_render_pass(std::vector<VkFormat>& color_attachments_format, VkImageLayout initial_layout, VkImageLayout final_layout) {
- std::vector<VkAttachmentDescription> attachments_description = {};
- std::vector<VkAttachmentReference> attachments_reference = {};
-
- for (size_t attachment_index = 0; attachment_index < color_attachments_format.size(); attachment_index++) {
- auto format = color_attachments_format[attachment_index];
- VkAttachmentDescription attachment_description = {};
- attachment_description.flags = 0;
- attachment_description.format = format;
- attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
- 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 = final_layout;
-
- attachments_description.push_back(attachment_description);
-
- VkAttachmentReference attachment_reference = {};
- attachment_reference.attachment = attachment_index;
- attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- attachments_reference.push_back(attachment_reference);
- }
-
- VkSubpassDescription subpass_description = {};
- subpass_description.flags = 0;
- subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass_description.colorAttachmentCount = attachments_reference.size();
- subpass_description.pColorAttachments = attachments_reference.data();
- subpass_description.pDepthStencilAttachment = VK_NULL_HANDLE;
- subpass_description.pResolveAttachments = VK_NULL_HANDLE;
- 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;
- create_info.pNext = VK_NULL_HANDLE;
- create_info.flags = 0;
- create_info.attachmentCount = attachments_description.size();
- create_info.pAttachments = attachments_description.data();
- create_info.subpassCount = 1;
- create_info.pSubpasses = &subpass_description;
- // create_info.dependencyCount = sizeof(subpass_dependency) / sizeof(VkSubpassDependency);
- // create_info.pDependencies = subpass_dependency;
-
- VKRESULT(vkCreateRenderPass(context.device, &create_info, VK_NULL_HANDLE, &render_pass))
-
- return render_pass;
-}
-
-void vkapi::destroy_render_pass(VkRenderPass render_pass) {
- vkDestroyRenderPass(context.device, render_pass, VK_NULL_HANDLE);
-}
-
-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 = &attachments_create_info;
- create_info.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
- create_info.renderPass = render_pass;
- 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_handle))
-
- return { .handle = framebuffer_handle, .size = size };
-}
-
-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, formats, size);
- }
-
- return framebuffers;
-}
-
-void vkapi::destroy_framebuffer(framebuffer framebuffer) const {
- VKRESULT(vkDeviceWaitIdle(context.device))
-
- vkDestroyFramebuffer(context.device, framebuffer.handle, VK_NULL_HANDLE);
-}
-
-void vkapi::destroy_framebuffers(std::vector<framebuffer>& framebuffers) const {
- VKRESULT(vkDeviceWaitIdle(context.device))
-
- for (auto& framebuffer : framebuffers) {
- vkDestroyFramebuffer(context.device, framebuffer.handle, VK_NULL_HANDLE);
- }
-}
-
-pipeline vkapi::create_compute_pipeline(const char* shader_name) const {
- pipeline pipeline{
- .bind_point = VK_PIPELINE_BIND_POINT_COMPUTE
- };
-
- auto shader_filename = std::string(shader_name) + ".comp.spv";
- auto shader_path = std::filesystem::path{ "./shaders" } / shader_filename;
- auto shader_code = read_file(shader_path.string().c_str());
- assert(!shader_code.empty());
-
- pipeline.shader_modules.resize(1);
-
- VkShaderModuleCreateInfo shader_create_info = {};
- shader_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- shader_create_info.pNext = VK_NULL_HANDLE;
- shader_create_info.flags = 0;
- shader_create_info.codeSize = shader_code.size();
- shader_create_info.pCode = reinterpret_cast<uint32_t*>(shader_code.data());
-
- VKRESULT(vkCreateShaderModule(context.device, &shader_create_info, VK_NULL_HANDLE, (pipeline.shader_modules).data()))
-
- VkPipelineShaderStageCreateInfo stage_create_info = {};
- stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- stage_create_info.pNext = VK_NULL_HANDLE;
- stage_create_info.flags = 0;
- stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
- stage_create_info.module = pipeline.shader_modules[0];
- stage_create_info.pName = "main";
- stage_create_info.pSpecializationInfo = VK_NULL_HANDLE;
-
-
- VkComputePipelineCreateInfo create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
- create_info.pNext = VK_NULL_HANDLE;
- create_info.flags = 0;
- create_info.stage = stage_create_info;
- create_info.layout = bindless_descriptor.pipeline_layout;
-
- VKRESULT(vkCreateComputePipelines(
- context.device,
- VK_NULL_HANDLE,
- 1,
- &create_info,
- nullptr,
- &pipeline.handle))
-
- return pipeline;
-}
-
-pipeline vkapi::create_graphics_pipeline(const char* shader_name, VkShaderStageFlagBits shader_stages, VkRenderPass render_pass, std::vector<VkDynamicState>& dynamic_states) const {
- pipeline pipeline{
- .bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS
- };
-
- std::vector<VkPipelineShaderStageCreateInfo> stages_create_info = {};
-
- for (VkShaderStageFlags stage_flag = VK_SHADER_STAGE_VERTEX_BIT; stage_flag <= VK_SHADER_STAGE_ALL_GRAPHICS; stage_flag <<= 2) {
- if ((stage_flag & shader_stages) != 0U) {
- VkShaderModule shader_module;
-
- auto shader_filename = std::string(shader_name) + shader_stage_extension(stage_flag) + ".spv";
- auto shader_path = std::filesystem::path{ "./shaders" } / shader_filename;
- std::vector<uint8_t> shader_code = read_file(shader_path.string().c_str());
- assert(!shader_code.empty());
-
- VkShaderModuleCreateInfo shader_create_info = {};
- shader_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- shader_create_info.pNext = nullptr;
- shader_create_info.flags = 0;
- shader_create_info.codeSize = shader_code.size();
- shader_create_info.pCode = reinterpret_cast<uint32_t*>(shader_code.data());
-
- VKRESULT(vkCreateShaderModule(context.device, &shader_create_info, nullptr, &shader_module))
-
- pipeline.shader_modules.push_back(shader_module);
-
- VkPipelineShaderStageCreateInfo stage_create_info = {};
- stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- stage_create_info.pNext = nullptr;
- stage_create_info.flags = 0;
- stage_create_info.stage = (VkShaderStageFlagBits)stage_flag;
- stage_create_info.module = shader_module;
- stage_create_info.pName = "main";
- stage_create_info.pSpecializationInfo = nullptr;
-
- stages_create_info.push_back(stage_create_info);
- }
- }
-
-
- VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = {};
- vertex_input_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
-
- VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = {};
- input_assembly_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- input_assembly_state_create_info.pNext = nullptr;
- input_assembly_state_create_info.flags = 0;
- input_assembly_state_create_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
-
- VkPipelineViewportStateCreateInfo viewport_state_create_info = {};
- viewport_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- viewport_state_create_info.pNext = nullptr;
- viewport_state_create_info.flags = 0;
- viewport_state_create_info.viewportCount = 1;
- viewport_state_create_info.pViewports = VK_NULL_HANDLE;
- viewport_state_create_info.scissorCount = 1;
- viewport_state_create_info.pScissors = VK_NULL_HANDLE;
-
- VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = {};
- rasterization_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
- rasterization_state_create_info.pNext = nullptr;
- rasterization_state_create_info.flags = 0;
- rasterization_state_create_info.depthClampEnable = VK_FALSE;
- rasterization_state_create_info.rasterizerDiscardEnable = VK_FALSE;
- rasterization_state_create_info.polygonMode = VK_POLYGON_MODE_FILL;
- rasterization_state_create_info.cullMode = VK_CULL_MODE_NONE;
- rasterization_state_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
- rasterization_state_create_info.depthBiasEnable = VK_FALSE;
- rasterization_state_create_info.lineWidth = 1.f;
-
- VkPipelineMultisampleStateCreateInfo multisample_state_create_info = {};
- multisample_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- multisample_state_create_info.pNext = nullptr;
- multisample_state_create_info.flags = 0;
- multisample_state_create_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
- multisample_state_create_info.sampleShadingEnable = VK_FALSE;
- multisample_state_create_info.minSampleShading = 1.f;
-
- VkPipelineColorBlendAttachmentState color_attachment_state = {};
- color_attachment_state.blendEnable = VK_TRUE;
- color_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
- color_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- color_attachment_state.colorBlendOp = VK_BLEND_OP_ADD;
- color_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
- color_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- color_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD;
- color_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
-
- VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = {};
- color_blend_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
- color_blend_state_create_info.pNext = nullptr;
- color_blend_state_create_info.flags = 0;
- color_blend_state_create_info.logicOpEnable = VK_FALSE;
- color_blend_state_create_info.attachmentCount = 1;
- color_blend_state_create_info.pAttachments = &color_attachment_state;
-
- VkPipelineDynamicStateCreateInfo dynamic_state_create_info = {};
- dynamic_state_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- dynamic_state_create_info.pNext = VK_NULL_HANDLE;
- dynamic_state_create_info.flags = 0;
- dynamic_state_create_info.dynamicStateCount = dynamic_states.size();
- dynamic_state_create_info.pDynamicStates = dynamic_states.data();
-
- VkGraphicsPipelineCreateInfo pipeline_create_info = {};
- pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- pipeline_create_info.pNext = nullptr;
- pipeline_create_info.flags = 0;
- pipeline_create_info.stageCount = stages_create_info.size();
- pipeline_create_info.pStages = stages_create_info.data();
- pipeline_create_info.pVertexInputState = &vertex_input_state_create_info;
- pipeline_create_info.pInputAssemblyState = &input_assembly_state_create_info;
- pipeline_create_info.pViewportState = &viewport_state_create_info;
- pipeline_create_info.pRasterizationState = &rasterization_state_create_info;
- pipeline_create_info.pMultisampleState = &multisample_state_create_info;
- pipeline_create_info.pColorBlendState = &color_blend_state_create_info;
- pipeline_create_info.pDynamicState = &dynamic_state_create_info;
- pipeline_create_info.layout = bindless_descriptor.pipeline_layout;
- pipeline_create_info.renderPass = render_pass;
- pipeline_create_info.subpass = 0;
-
- VKRESULT(vkCreateGraphicsPipelines(context.device, VK_NULL_HANDLE, 1, &pipeline_create_info, VK_NULL_HANDLE, &pipeline.handle))
-
- return pipeline;
-}
-
-void vkapi::destroy_pipeline(pipeline& pipeline) const {
- for (auto& shader_module : pipeline.shader_modules) {
- vkDestroyShaderModule(context.device, shader_module, nullptr);
- }
-
- vkDestroyPipeline(context.device, pipeline.handle, nullptr);
-}
-
-VkSurfaceKHR vkapi::create_surface(window& wnd) const {
- VkSurfaceKHR surface;
-
-#if defined(LINUX)
- VkXcbSurfaceCreateInfoKHR create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = nullptr;
- create_info.flags = 0;
- create_info.connection = wnd.connection;
- create_info.window = wnd.win;
-
- VKRESULT(vkCreateXcbSurfaceKHR(context.instance, &create_info, nullptr, &surface))
-#elif defined(WINDOWS)
- VkWin32SurfaceCreateInfoKHR create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
- create_info.pNext = nullptr;
- create_info.flags = 0;
- create_info.hinstance = GetModuleHandle(nullptr);
- create_info.hwnd = wnd.handle;
-
- VKRESULT(vkCreateWin32SurfaceKHR(context.instance, &create_info, nullptr, &surface))
-#elif defined(MACOS)
- VkMetalSurfaceCreateInfoEXT create_info = {};
- create_info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
- create_info.pNext = nullptr;
- create_info.flags = 0;
- // create_info.pLayer = GetModuleHandle(NULL);
-
- VKRESULT(vkCreateMetalSurfaceEXT(context.instance, &create_info, nullptr, &surface))
-#endif
-
- return surface;
-}
-
-void vkapi::destroy_surface(VkSurfaceKHR surface) {
- vkDestroySurfaceKHR(context.instance, surface, nullptr);
-}
-
-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.graphics_queue.index, surface, &queue_support_presentation))
-
- assert(queue_support_presentation == VK_TRUE);
-
- VkSurfaceCapabilitiesKHR caps;
- VKRESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context.physical_device, surface, &caps))
-
- swapchain.extent = caps.currentExtent;
-
- if (swapchain.extent.width < caps.minImageExtent.width) {
- swapchain.extent.width = caps.minImageExtent.width;
- } else if (swapchain.extent.width > caps.maxImageExtent.width) {
- swapchain.extent.width = caps.maxImageExtent.width;
- }
-
- if (swapchain.extent.height < caps.minImageExtent.height) {
- swapchain.extent.height = caps.minImageExtent.height;
- } else if (swapchain.extent.height > caps.maxImageExtent.height) {
- 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 = {};
- create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- create_info.pNext = nullptr;
- create_info.flags = 0;
- create_info.surface = surface;
- create_info.minImageCount = min_image_count;
- create_info.imageFormat = swapchain.surface_format.format;
- create_info.imageColorSpace = swapchain.surface_format.colorSpace;
- create_info.imageExtent = swapchain.extent;
- create_info.imageArrayLayers = 1;
- create_info.imageUsage = usages;
- create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- create_info.preTransform = caps.currentTransform;
- create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_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))
-
-
- 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()))
-
-
- VkImageSubresourceRange image_subresource_range = {};
- 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;
-
- VkExtent3D image_size = {
- .width = swapchain.extent.width,
- .height = swapchain.extent.height,
- .depth = 1,
- };
-
- for (size_t image_index = 0; image_index < swapchain.image_count; image_index++) {
- auto* 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;
-
-
- 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 = 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 = {
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY,
- VK_COMPONENT_SWIZZLE_IDENTITY
- };
- 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);
-
- auto current_image_handle = images.size() - 1;
-
- if ((usages & VK_IMAGE_USAGE_STORAGE_BIT) != 0U) {
- current_image->bindless_storage_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- update_descriptor_image(current_image_handle, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- }
-
- if ((usages & VK_IMAGE_USAGE_SAMPLED_BIT) != 0U) {
- current_image->bindless_sampled_index = bindless_descriptor.allocate(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
- update_descriptor_image(current_image_handle, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
- }
-
- swapchain.images[image_index] = current_image_handle;
- }
-
- return swapchain;
-}
-
-void vkapi::destroy_swapchain(swapchain& swapchain) {
- VKRESULT(vkDeviceWaitIdle(context.device))
-
- for (auto& image : swapchain.images) {
- // TODO: Change this
- if (images[image]->bindless_storage_index != 0)
- bindless_descriptor.free(images[image]->bindless_storage_index, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
- if (images[image]->bindless_sampled_index != 0)
- bindless_descriptor.free(images[image]->bindless_sampled_index, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
-
- vkDestroyImageView(context.device, images[image]->view, nullptr);
- }
- vkDestroySwapchainKHR(context.device, swapchain.handle, nullptr);
-}
-
-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 = 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 ? current_image->bindless_storage_index : current_image->bindless_sampled_index;
- write_descriptor.descriptorCount = 1;
- write_descriptor.descriptorType = type;
- write_descriptor.pImageInfo = &descriptor_image_info;
- write_descriptor.pBufferInfo = VK_NULL_HANDLE;
- write_descriptor.pTexelBufferView = VK_NULL_HANDLE;
-
- vkUpdateDescriptorSets(context.device, 1, &write_descriptor, 0, nullptr);
-}
-
-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[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].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].descriptorCount = 1;
- writes_descriptor[image_index].descriptorType = type;
- writes_descriptor[image_index].pImageInfo = &descriptor_images_info[image_index];
- writes_descriptor[image_index].pBufferInfo = VK_NULL_HANDLE;
- writes_descriptor[image_index].pTexelBufferView = VK_NULL_HANDLE;
- }
-
- vkUpdateDescriptorSets(context.device, writes_descriptor.size(), writes_descriptor.data(), 0, nullptr);
-}
-
-void vkapi::update_descriptor_sampler(handle sampler) {
- VkDescriptorImageInfo descriptor_image_info;
- VkWriteDescriptorSet write_descriptor;
- auto current_sampler = samplers[sampler];
-
- descriptor_image_info.sampler = current_sampler->handle;
- descriptor_image_info.imageView = VK_NULL_HANDLE;
- 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 = 0;
- write_descriptor.dstArrayElement = current_sampler->bindless_index;
- write_descriptor.descriptorCount = 1;
- write_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
- write_descriptor.pImageInfo = &descriptor_image_info;
- write_descriptor.pBufferInfo = VK_NULL_HANDLE;
- write_descriptor.pTexelBufferView = VK_NULL_HANDLE;
-
- vkUpdateDescriptorSets(context.device, 1, &write_descriptor, 0, nullptr);
-}
-
-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++) {
- 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;
-
- writes_descriptor[sampler_index].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- 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 = 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];
- writes_descriptor[sampler_index].pBufferInfo = VK_NULL_HANDLE;
- writes_descriptor[sampler_index].pTexelBufferView = VK_NULL_HANDLE;
- }
-
- vkUpdateDescriptorSets(context.device, writes_descriptor.size(), writes_descriptor.data(), 0, nullptr);
-}
-
-void vkapi::update_constants(VkCommandBuffer command_buffer, VkShaderStageFlagBits shader_stage, off_t offset, size_t size, void* data) {
- vkCmdPushConstants(command_buffer, bindless_descriptor.pipeline_layout, shader_stage, offset, size, data);
-}
-
-void vkapi::start_record(VkCommandBuffer command_buffer) {
- VkCommandBufferBeginInfo cmd_buf_begin_info = {};
- cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- cmd_buf_begin_info.pNext = nullptr;
- cmd_buf_begin_info.flags = 0;
- cmd_buf_begin_info.pInheritanceInfo = nullptr;
-
- vkBeginCommandBuffer(command_buffer, &cmd_buf_begin_info);
-}
-
-void vkapi::image_barrier(VkCommandBuffer command_buffer, VkImageLayout dst_layout, VkPipelineStageFlagBits dst_stage, VkAccessFlags dst_access, handle image) {
- auto* current_image = images[image];
-
- VkImageMemoryBarrier image_barrier = {};
- image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- image_barrier.pNext = nullptr;
- image_barrier.srcAccessMask = current_image->previous_access;
- image_barrier.dstAccessMask = dst_access;
- image_barrier.oldLayout = current_image->previous_layout;
- image_barrier.newLayout = dst_layout;
- image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- image_barrier.image = current_image->handle;
- image_barrier.subresourceRange = current_image->subresource_range;
-
- vkCmdPipelineBarrier(
- command_buffer,
- current_image->previous_stage,
- dst_stage,
- 0,
- 0,
- nullptr,
- 0,
- nullptr,
- 1,
- &image_barrier);
-
- 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, std::vector<VkImageView>& attachments, framebuffer framebuffer, VkExtent2D size) {
- VkRect2D render_area = {
- {
- 0,
- 0,
- },
- 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{ .color{ .float32{ 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 = &attachment_begin_info;
- render_pass_begin_info.renderPass = render_pass;
- 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);
-}
-
-void vkapi::end_render_pass(VkCommandBuffer command_buffer) {
- vkCmdEndRenderPass(command_buffer);
-}
-
-void vkapi::run_compute_pipeline(VkCommandBuffer command_buffer, pipeline& pipeline, size_t group_count_x, size_t group_count_y, size_t group_count_z) {
- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless_descriptor.pipeline_layout, 0, 1, &bindless_descriptor.set, 0, nullptr);
-
- vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.handle);
-
- vkCmdDispatch(command_buffer, group_count_x, group_count_y, group_count_z);
-}
-
-void vkapi::draw(VkCommandBuffer command_buffer, pipeline& pipeline, uint32_t vertex_count, uint32_t vertex_offset) {
- 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);
-
- vkCmdDraw(command_buffer, vertex_count, 1, vertex_offset, 0);
-}
-
-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, 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,
- .baseArrayLayer = 0,
- .layerCount = 1,
- };
-
- VkOffset3D start_offset{
- .x = 0,
- .y = 0,
- .z = 0,
- };
- VkOffset3D end_offset{
- .x = (int32_t)dst_image->size.width,
- .y = (int32_t)dst_image->size.height,
- .z = (int32_t)dst_image->size.depth,
- };
-
- VkImageBlit blit_region{
- .srcSubresource = images_subres_layers,
- .srcOffsets = { start_offset, end_offset },
- .dstSubresource = images_subres_layers,
- .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);
-}
-
-void vkapi::end_record(VkCommandBuffer command_buffer){
- VKRESULT(vkEndCommandBuffer(command_buffer))
-}
-
-VkResult vkapi::submit(VkCommandBuffer command_buffers[], size_t command_buffers_count, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence submission_fence) const {
- VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
-
- VkSubmitInfo submit_info = {};
- submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submit_info.pNext = nullptr;
- submit_info.waitSemaphoreCount = wait_semaphore != nullptr ? 1 : 0;
- submit_info.pWaitSemaphores = &wait_semaphore;
- submit_info.pWaitDstStageMask = wait_semaphore != nullptr ? &wait_stage : VK_NULL_HANDLE;
- submit_info.signalSemaphoreCount = signal_semaphore != nullptr ? 1 : 0;
- submit_info.pSignalSemaphores = &signal_semaphore;
- submit_info.commandBufferCount = command_buffers_count;
- submit_info.pCommandBuffers = command_buffers;
-
- return vkQueueSubmit(context.graphics_queue.handle, 1, &submit_info, submission_fence);
-}
-
-VkResult vkapi::present(swapchain& swapchain, uint32_t image_index, VkSemaphore wait_semaphore) const {
- VkPresentInfoKHR present_info = {};
- present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- present_info.pNext = nullptr;
- present_info.waitSemaphoreCount = 1;
- present_info.pWaitSemaphores = &wait_semaphore;
- present_info.swapchainCount = 1;
- present_info.pSwapchains = &swapchain.handle;
- present_info.pImageIndices = &image_index;
- present_info.pResults = nullptr;
-
- return vkQueuePresentKHR(context.graphics_queue.handle, &present_info);
-}
-
-const char* vkapi::shader_stage_extension(VkShaderStageFlags shader_stage) {
- switch (shader_stage) {
- case VK_SHADER_STAGE_VERTEX_BIT: {
- return ".vert";
- }
- case VK_SHADER_STAGE_FRAGMENT_BIT: {
- return ".frag";
- }
- case VK_SHADER_STAGE_COMPUTE_BIT: {
- return ".comp";
- }
- default:
- assert(true && "Stage not supported");
- return "";
- }
-}
diff --git a/src/vk-bindless.cpp b/src/vk-bindless.cpp
new file mode 100644
index 0000000..9e517df
--- /dev/null
+++ b/src/vk-bindless.cpp
@@ -0,0 +1,238 @@
+#include "vk-bindless.hpp"
+
+#include "vk-device.hpp"
+#include "vk-utils.hpp"
+
+device_buffer& bindless_model::get_uniform_buffer(enum UniformTypes type) const {
+ return vkdevice::get().get_buffer(uniform_buffers[type]);
+}
+
+void bindless_model::init() {
+ vkdevice& render_device = vkdevice::get();
+ VkDevice device = render_device.get_device();
+
+ // -------------------------
+ // create immutable samplers
+ // -------------------------
+ {
+ VkSamplerCreateInfo create_info{
+ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ .pNext = VK_NULL_HANDLE,
+ .flags = 0,
+ .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ .mipLodBias = 0.f,
+ .anisotropyEnable = VK_FALSE,
+ .compareEnable = VK_FALSE,
+ .compareOp = VK_COMPARE_OP_NEVER,
+ .minLod = 0.f,
+ .maxLod = 0.f,
+ .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+ .unnormalizedCoordinates = VK_FALSE,
+ };
+
+ // Nearest sampler
+ {
+ VkFilter filter = VK_FILTER_NEAREST;
+ VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+
+ create_info.magFilter = filter,
+ create_info.minFilter = filter,
+ create_info.addressModeU = address_mode,
+ create_info.addressModeV = address_mode,
+ create_info.addressModeW = address_mode,
+
+ VKCHECK(vkCreateSampler(device, &create_info, VK_NULL_HANDLE, &samplers[SamplerType::NEAREST]));
+ }
+
+ // Linear sampler
+ {
+ VkFilter filter = VK_FILTER_LINEAR;
+ VkSamplerAddressMode address_mode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+
+ create_info.magFilter = filter,
+ create_info.minFilter = filter,
+ create_info.addressModeU = address_mode,
+ create_info.addressModeV = address_mode,
+ create_info.addressModeW = address_mode,
+
+ VKCHECK(vkCreateSampler(device, &create_info, VK_NULL_HANDLE, &samplers[SamplerType::LINEAR]));
+ }
+ }
+
+ // Set 0 global resources
+ // Binding 0 Storage images
+ // Binding 1 Sampled images
+ // Binding 2 Samplers
+ {
+ VkDescriptorSetLayoutBinding set_layout_bindings[]{
+ {
+ .binding = 0U,
+ .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
+ .descriptorCount = SamplerType::MAX_SAMPLER,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
+ .pImmutableSamplers = samplers,
+ },
+ {
+ .binding = 1U,
+ .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ .descriptorCount = set_descriptors_count,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
+ .pImmutableSamplers = nullptr,
+ },
+ {
+ .binding = 2U,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .descriptorCount = set_descriptors_count,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
+ .pImmutableSamplers = nullptr,
+ },
+ };
+
+ VkDescriptorBindingFlags flags[]{
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
+ VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
+ };
+
+ VkDescriptorSetLayoutBindingFlagsCreateInfo layout_binding_flags{
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+ .pNext = VK_NULL_HANDLE,
+ .bindingCount = sizeof(flags) / sizeof(VkDescriptorBindingFlags),
+ .pBindingFlags = flags,
+ };
+
+ VkDescriptorSetLayoutCreateInfo create_info{
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .pNext = &layout_binding_flags,
+ .flags = 0U,
+ .bindingCount = sizeof(set_layout_bindings) / sizeof(VkDescriptorSetLayoutBinding),
+ .pBindings = set_layout_bindings,
+ };
+
+ VKCHECK(vkCreateDescriptorSetLayout(device, &create_info, nullptr, &global_set_layout));
+ }
+
+ // ----------------------
+ // create layout
+ // ----------------------
+ {
+ VkPushConstantRange push_constant {
+ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT,
+ .offset = 0U,
+ .size = push_constant_slot_size * push_constant_slots,
+ };
+
+ VkPipelineLayoutCreateInfo create_info{
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0U,
+ .setLayoutCount = 1U,
+ .pSetLayouts = &global_set_layout,
+ .pushConstantRangeCount = 1U,
+ .pPushConstantRanges = &push_constant,
+ };
+
+ VKCHECK(vkCreatePipelineLayout(device, &create_info, nullptr, &global_layout));
+ }
+
+ // ----------------------
+ // create descriptor pool
+ // ----------------------
+ {
+ VkDescriptorPoolSize pool_sizes[]{
+ {
+ .type = VK_DESCRIPTOR_TYPE_SAMPLER,
+ .descriptorCount = set_descriptors_count,
+ },
+ {
+ .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ .descriptorCount = set_descriptors_count,
+ },
+ {
+ .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .descriptorCount = set_descriptors_count,
+ },
+ };
+
+ VkDescriptorPoolCreateInfo descriptor_pool_create_info{
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0U,
+ .maxSets = descriptor_pool_allocable_sets_count,
+ .poolSizeCount = sizeof(pool_sizes) / sizeof(VkDescriptorPoolSize),
+ .pPoolSizes = pool_sizes,
+ };
+ VKCHECK(vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool));
+ }
+
+ // -----------------------
+ // create descriptors sets
+ // -----------------------
+ {
+ VkDescriptorSetAllocateInfo allocate_info{
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .descriptorPool = descriptor_pool,
+ .descriptorSetCount = 1U,
+ .pSetLayouts = &global_set_layout,
+ };
+ VKCHECK(vkAllocateDescriptorSets(device, &allocate_info, &global_set));
+ }
+
+ // ---------------------
+ // global uniform buffer
+ // ---------------------
+ {
+ uniform_buffers[UniformTypes::GLOBAL] = render_device.create_buffer({
+ .size = globals_uniform_buffer_size,
+ .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "global uniform buffer",
+ });
+ }
+
+ // ---------------------
+ // passes uniform buffer
+ // ---------------------
+ {
+ uniform_buffers[UniformTypes::PASS] = render_device.create_buffer({
+ .size = passes_uniform_buffer_size,
+ .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "passes uniform buffer"
+ });
+ }
+
+ // --------------------
+ // draws uniform buffer
+ // --------------------
+ {
+ uniform_buffers[UniformTypes::DRAW] = render_device.create_buffer({
+ .size = draws_uniform_buffer_size,
+ .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
+ .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+ .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "draws uniform buffer",
+ });
+ }
+}
+
+void bindless_model::deinit() {
+ vkdevice& render_device = vkdevice::get();
+ VkDevice device = render_device.get_device();
+
+ vkDestroyDescriptorPool(device, descriptor_pool, nullptr);
+
+ vkDestroyDescriptorSetLayout(device, global_set_layout, nullptr);
+ vkDestroyPipelineLayout(device, global_layout, nullptr);
+
+ render_device.destroy_buffer(uniform_buffers[UniformTypes::GLOBAL]);
+ render_device.destroy_buffer(uniform_buffers[UniformTypes::PASS]);
+ render_device.destroy_buffer(uniform_buffers[UniformTypes::DRAW]);
+
+ for (VkSampler sampler : samplers) {
+ vkDestroySampler(device, sampler, nullptr);
+ }
+}
diff --git a/api-test/vk-command-buffer.cpp b/src/vk-command-buffer.cpp
index bdb0e40..26c2d03 100644
--- a/api-test/vk-command-buffer.cpp
+++ b/src/vk-command-buffer.cpp
@@ -1,11 +1,6 @@
#include "vk-command-buffer.hpp"
-#include <vulkan/vulkan_core.h>
-
-#include "vulkan-loader.hpp"
-
-#include "vk-device.hpp"
-#include "vk-utils.hpp"
+uintptr_t constants[3U] = { 0U };
void command_buffer::start() const {
VkCommandBufferBeginInfo begin_info{
@@ -17,20 +12,15 @@ void command_buffer::start() const {
VKCHECK(vkBeginCommandBuffer(vk_command_buffer, &begin_info));
- const auto& bindless = vkdevice::get_render_device().get_bindingmodel();
- const auto* global_set = &bindless.sets[BindlessSetType::GLOBAL];
- // const auto global_uniforms = bindless.get_globals_uniform_buffer();
- // if (queue_type == QueueType::GRAPHICS) {
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.graphics_layout, 0, 1U, global_set, 1U, &global_uniforms.offset);
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 1U, &global_uniforms.offset);
- // } else if (queue_type == QueueType::ASYNC_COMPUTE) {
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 1U, &global_uniforms.offset);
- // }
+ const bindless_model& bindless = vkdevice::get().get_bindingmodel();
+ const device_buffer& global_uniforms = bindless.get_uniform_buffer(UniformTypes::GLOBAL);
+ constants[UniformTypes::GLOBAL] = global_uniforms.device_address + global_uniforms.offset;
+
if (queue_type == QueueType::GRAPHICS) {
- vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.graphics_layout, 0, 1U, global_set, 0U, nullptr);
- vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 0U, nullptr);
+ vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.global_layout, 0, 1U, &bindless.global_set, 0U, nullptr);
+ vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.global_layout, 0, 1U, &bindless.global_set, 0U, nullptr);
} else if (queue_type == QueueType::ASYNC_COMPUTE) {
- vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, 0, 1U, global_set, 0U, nullptr);
+ vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.global_layout, 0, 1U, &bindless.global_set, 0U, nullptr);
}
}
@@ -39,7 +29,7 @@ void command_buffer::stop() const {
}
void command_buffer::barrier(handle<device_texture> texture_handle, VkPipelineStageFlags2 stage, VkAccessFlags2 access, VkImageLayout layout) const {
- auto& texture = vkdevice::get_render_device().get_texture(texture_handle);
+ auto& texture = vkdevice::get().get_texture(texture_handle);
VkImageSubresourceRange subresource_range{
.aspectMask = texture.aspects,
@@ -83,7 +73,7 @@ void command_buffer::barrier(handle<device_texture> texture_handle, VkPipelineSt
}
void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_texture> texture_handle, uint64_t offset) const {
- auto& device = vkdevice::get_render_device();
+ auto& device = vkdevice::get();
const auto& buffer = device.get_buffer(buffer_handle);
const auto& texture = device.get_texture(texture_handle);
@@ -111,17 +101,15 @@ void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_t
}
void graphics_command_buffer::dispatch(const dispatch_params& params) const {
- const auto& pipeline = vkdevice::get_render_device().get_pipeline(params.pipeline);
- const auto& bindless = vkdevice::get_render_device().get_bindingmodel();
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, static_cast<uint32_t>(BindlessSetType::INSTANCES_UNIFORMS), 1U, &bindless.sets[BindlessSetType::INSTANCES_UNIFORMS], 1U, &params.uniforms_offset);
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.compute_layout, static_cast<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, &params.uniforms_offset);
-
- for (uint32_t push_index = 0U; push_index < bindless_model::max_push_constants_slots; push_index++) {
- vkCmdPushConstants(vk_command_buffer, bindless.compute_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_index * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.params[push_index]);
- }
+ const device_pipeline& pipeline = vkdevice::get().get_pipeline(params.pipeline);
+ const bindless_model& bindless = vkdevice::get().get_bindingmodel();
vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline);
+ const device_buffer& draw_uniforms = bindless.get_uniform_buffer(UniformTypes::DRAW);
+ constants[UniformTypes::DRAW] = draw_uniforms.device_address + draw_uniforms.offset;
+ vkCmdPushConstants(vk_command_buffer, bindless.global_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0U, sizeof(constants), &constants);
+
auto x = params.group_size.vec.x / params.local_group_size.vec.x;
auto y = params.group_size.vec.y / params.local_group_size.vec.y;
auto z = params.group_size.vec.z / params.local_group_size.vec.z;
@@ -133,7 +121,7 @@ void graphics_command_buffer::begin_renderpass(const renderpass_params& params)
for (auto index{ 0U }; index < params.color_attachments.size(); index++) {
auto& attachment_info = attachments_info[index];
- auto& attachment = vkdevice::get_render_device().get_texture(params.color_attachments[index]);
+ auto& attachment = vkdevice::get().get_texture(params.color_attachments[index]);
attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
attachment_info.pNext = nullptr;
@@ -183,45 +171,40 @@ void graphics_command_buffer::begin_renderpass(const renderpass_params& params)
};
vkCmdBeginRendering(vk_command_buffer, &rendering_info);
+ const bindless_model& bindless = vkdevice::get().get_bindingmodel();
+ const device_buffer& pass_uniforms = bindless.get_uniform_buffer(UniformTypes::PASS);
+ constants[UniformTypes::PASS] = pass_uniforms.device_address + pass_uniforms.offset;
+
vkCmdSetScissor(vk_command_buffer, 0U, 1U, &scissor);
vkCmdSetViewport(vk_command_buffer, 0U, 1U, &viewport);
-
- // auto& device = vkdevice::get_render_device();
- // const auto& bindless = device.get_bindingmodel();
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, bindless.layout, static_cast<uint32_t>(BindlessSetType::GLOBAL), 1U, &bindless.sets[BindlessSetType::GLOBAL], 1U, &params.uniforms_offset);
- // vkCmdBindDescriptorSets(vk_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bindless.layout, static_cast<uint32_t>(BindlessSetType::GLOBAL), 1U, &bindless.sets[BindlessSetType::GLOBAL], 1U, &params.uniforms_offset);
}
void graphics_command_buffer::draw(const draw_params& params) const {
- auto& device = vkdevice::get_render_device();
+ auto& device = vkdevice::get();
const auto& pipeline = device.get_pipeline(params.pipeline);
const auto& bindless = device.get_bindingmodel();
- // vkCmdBindDescriptorSets(vk_command_buffer, pipeline.bind_point, bindless.layout, static_cast<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, &params.uniforms_offset);
vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::GLOBALS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.globals_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::INSTANCES * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.instances_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::DRAWS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.uniforms_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::VERTEX_BUFFER * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.vertex_address);
+ const device_buffer& draw_uniforms = bindless.get_uniform_buffer(UniformTypes::DRAW);
+ constants[UniformTypes::DRAW] = draw_uniforms.device_address + draw_uniforms.offset;
+ vkCmdPushConstants(vk_command_buffer, bindless.global_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0U, sizeof(constants), &constants);
vkCmdDraw(vk_command_buffer, params.vertex_count, params.instance_count, params.vertex_offset, 0U);
}
void graphics_command_buffer::draw_indexed(const draw_indexed_params& params) const {
- auto& device = vkdevice::get_render_device();
+ auto& device = vkdevice::get();
const auto& pipeline = device.get_pipeline(params.pipeline);
const auto& bindless = device.get_bindingmodel();
- // vkCmdBindDescriptorSets(vk_command_buffer, pipeline.bind_point, bindless.layout, static_cast<uint32_t>(BindlessSetType::DRAWS_UNIFORMS), 1U, &bindless.sets[BindlessSetType::DRAWS_UNIFORMS], 1U, &params.uniforms_offset);
vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::GLOBALS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.globals_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::INSTANCES * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.instances_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::DRAWS * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.uniforms_address);
- vkCmdPushConstants(vk_command_buffer, bindless.graphics_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, ConstantType::VERTEX_BUFFER * bindless_model::max_push_constants_slots_size, bindless_model::max_push_constants_slots_size, &params.vertex_address);
+ const device_buffer& draw_uniforms = bindless.get_uniform_buffer(UniformTypes::DRAW);
+ constants[UniformTypes::DRAW] = draw_uniforms.device_address + draw_uniforms.offset;
+ vkCmdPushConstants(vk_command_buffer, bindless.global_layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0U, sizeof(constants), &constants);
const auto& index_buffer = device.get_buffer(params.index_buffer);
vkCmdBindIndexBuffer(vk_command_buffer, index_buffer.vk_buffer, 0U, VK_INDEX_TYPE_UINT16);
diff --git a/src/vk-context.cpp b/src/vk-context.cpp
deleted file mode 100644
index 1a6a78d..0000000
--- a/src/vk-context.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-#include "vk-context.hpp"
-
-#include <iostream>
-#include <cassert>
-#include <vector>
-#include <array>
-
-#define VMA_IMPLEMENTATION
-#include <vk_mem_alloc.h>
-
-#include "vulkan-loader.hpp"
-
-#ifdef _DEBUG
-#define VKRESULT(result) assert(result == VK_SUCCESS);
-#else
-#define VKRESULT(result) result;
-#endif
-
-VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
- VkDebugUtilsMessageTypeFlagsEXT type,
- const VkDebugUtilsMessengerCallbackDataEXT *data,
- void*)
-{
- const char* severity_cstr = nullptr;
- switch(severity) {
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
- severity_cstr = "VERBOSE";
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
- severity_cstr = "INFO";
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
- severity_cstr = "WARNING";
- break;
- case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
- severity_cstr = "ERROR";
- break;
- default:
- break;
- }
-
- const char* type_cstr = nullptr;
- switch(type) {
- case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
- type_cstr = "GENERAL";
- break;
- case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT:
- type_cstr = "VALIDATION";
- break;
- case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT:
- type_cstr = "PERFORMANCE";
- break;
- default:
- break;
- }
-
- std::cerr << "[" << severity_cstr << "_" << type_cstr << "]: " << data->pMessage << std::endl;
- return VK_FALSE;
-}
-
-
-vkcontext::vkcontext() {
- load_vulkan();
-
- create_instance();
- create_device();
- create_debugger();
- create_memory_allocator();
-}
-
-vkcontext::~vkcontext() {
- vmaDestroyAllocator(allocator);
- vkDestroyDevice(device, nullptr);
- vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
- vkDestroyInstance(instance, nullptr);
-}
-
-
-void vkcontext::create_instance() {
- VkApplicationInfo app_info = {};
- app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- app_info.pApplicationName = "path-tracer";
- app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
- app_info.pEngineName = "gpu-path-tracer";
- app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
- app_info.apiVersion = VK_API_VERSION_1_2;
-
- const char* needed_layers[] = {
-#if defined(_DEBUG)
- "VK_LAYER_KHRONOS_validation",
-#endif
- };
- auto needed_layers_count = sizeof(needed_layers) / sizeof(needed_layers[0]);
-
- check_available_instance_layers(needed_layers, needed_layers_count);
-
- constexpr const char* needed_extensions[] = {
- VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
- "VK_KHR_surface",
-#if defined(LINUX)
- "VK_KHR_xcb_surface"
-#elif defined(WINDOWS)
- "VK_KHR_win32_surface"
-#elif defined(MACOS)
- "VK_EXT_metal_surface"
-#endif
- };
- constexpr auto needed_extensions_count = sizeof(needed_extensions) / sizeof(needed_extensions[0]);
-
- check_available_instance_extensions(needed_extensions, needed_extensions_count);
-
- VkInstanceCreateInfo instance_create_info = {};
- instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- instance_create_info.pApplicationInfo = &app_info;
- instance_create_info.enabledLayerCount = needed_layers_count;
- instance_create_info.ppEnabledLayerNames = needed_layers;
- instance_create_info.enabledExtensionCount = needed_extensions_count;
- instance_create_info.ppEnabledExtensionNames = needed_extensions;
-
- VKRESULT(vkCreateInstance(&instance_create_info, nullptr, &instance))
-
- load_instance_functions(instance);
-
- std::cerr << "Instance ready" << std::endl;
-}
-
-void vkcontext::create_debugger() {
- VkDebugUtilsMessengerCreateInfoEXT debugUtilsMessengeCreateInfo {
- VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
- nullptr,
- 0,
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
- VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
- | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
- DebugCallback,
- nullptr,
- };
-
- VKRESULT(vkCreateDebugUtilsMessengerEXT(
- instance,
- &debugUtilsMessengeCreateInfo,
- nullptr,
- &debugMessenger
- ))
-}
-
-void vkcontext::create_device() {
- select_physical_device();
-
- graphics_queue = {
- .usages = VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT,
- };
- auto queue_priority = 1.f;
- graphics_queue.index = select_queue(graphics_queue.usages);
- auto queue_create_info = VkDeviceQueueCreateInfo {
- .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
- .queueFamilyIndex = graphics_queue.index,
- .queueCount = 1,
-
- .pQueuePriorities = &queue_priority
- };
-
- VkPhysicalDeviceVulkan12Features physical_device_12_features = {};
- physical_device_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
- physical_device_12_features.pNext = VK_NULL_HANDLE;
- physical_device_12_features.bufferDeviceAddress = VK_TRUE;
- physical_device_12_features.runtimeDescriptorArray = VK_TRUE;
- physical_device_12_features.shaderStorageImageArrayNonUniformIndexing = VK_TRUE;
- physical_device_12_features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE;
- 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;
- device_features.pNext = &physical_device_12_features;
-
- const char* device_ext[] = {
- "VK_KHR_swapchain",
- };
-
- VkDeviceCreateInfo device_create_info = {};
- device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- device_create_info.pNext = &device_features;
- device_create_info.pQueueCreateInfos = &queue_create_info;
- device_create_info.queueCreateInfoCount = 1;
- device_create_info.ppEnabledExtensionNames = device_ext;
- device_create_info.enabledExtensionCount = sizeof(device_ext) / sizeof(device_ext[0]);
- device_create_info.enabledLayerCount = 0; // Deprecated https://www.khronos.org/registry/vulkan/specs/1.2/html/chap31.html#extendingvulkan-layers-devicelayerdeprecation
-
- VKRESULT(vkCreateDevice(physical_device, &device_create_info, nullptr, &device))
-
- load_device_functions(device);
-
- vkGetDeviceQueue(device, graphics_queue.index, 0, &graphics_queue.handle);
-
- std::cerr << "Device ready" << std::endl;
-}
-
-void vkcontext::create_memory_allocator() {
- VmaAllocatorCreateInfo allocator_info = {};
- allocator_info.vulkanApiVersion = VK_API_VERSION_1_2;
- allocator_info.physicalDevice = physical_device;
- allocator_info.device = device;
- allocator_info.instance = instance;
- allocator_info.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
-
- vmaCreateAllocator(&allocator_info, &allocator);
-}
-
-
-void vkcontext::select_physical_device() {
- uint32_t physical_devices_count = 0;
- vkEnumeratePhysicalDevices(instance, &physical_devices_count, nullptr);
-
- if (physical_devices_count < 1) {
- std::cerr << "No physical device found !" << std::endl;
- }
-
- std::vector<VkPhysicalDevice> physical_devices { physical_devices_count };
- vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data());
-
-
- for (auto& physical_dev: physical_devices) {
- if (support_required_features(physical_dev)) {
- physical_device = physical_dev;
- }
- }
-
- assert(physical_device != VK_NULL_HANDLE);
-}
-
-uint32_t vkcontext::select_queue(VkQueueFlags queue_usage) const {
- uint32_t queue_properties_count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr);
-
- std::vector<VkQueueFamilyProperties> queue_properties { queue_properties_count };
- vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data());
-
- for (uint32_t properties_index = 0; properties_index < queue_properties_count; properties_index++) {
- if ((queue_properties[properties_index].queueFlags & queue_usage) != 0U) {
- return properties_index;
- }
- }
-
- assert(true);
- return UINT_MAX;
-}
-
-void vkcontext::check_available_instance_layers(const char* needed_layers[], size_t needed_layers_count) {
- uint32_t property_count = 0;
- vkEnumerateInstanceLayerProperties(&property_count, VK_NULL_HANDLE);
-
- std::vector<VkLayerProperties> layer_properties { property_count };
- vkEnumerateInstanceLayerProperties(&property_count, layer_properties.data());
-
- uint32_t available_needed_layers_count = 0;
-
- for (auto layer_property: layer_properties) {
- for (auto layer_index { 0U }; layer_index < needed_layers_count; layer_index++) {
- if (strcmp(layer_property.layerName, needed_layers[layer_index]) == 0) {
- available_needed_layers_count++;
- }
- }
- }
-
- assert(available_needed_layers_count == needed_layers_count);
-}
-
-void vkcontext::check_available_instance_extensions(const char* needed_extensions[], size_t needed_extensions_count) {
- uint32_t vulkan_extensions_count = 0;
- vkEnumerateInstanceExtensionProperties(VK_NULL_HANDLE, &vulkan_extensions_count, VK_NULL_HANDLE);
-
- std::vector<VkExtensionProperties> vulkan_extensions_properties { vulkan_extensions_count };
- vkEnumerateInstanceExtensionProperties(VK_NULL_HANDLE, &vulkan_extensions_count, vulkan_extensions_properties.data());
-
- uint32_t available_needed_extensions_count = 0;
- for (auto& extension: vulkan_extensions_properties) {
- for (auto extension_index { 0U }; extension_index < needed_extensions_count; extension_index++) {
- if (strcmp(extension.extensionName, needed_extensions[extension_index]) == 0) {
- available_needed_extensions_count++;
- }
- }
- }
-
- // assert(available_needed_extensions_count == needed_extensions_count);
-}
-
-bool vkcontext::support_required_features(VkPhysicalDevice physical_device) {
- VkPhysicalDeviceProperties physical_device_properties = {};
-
- vkGetPhysicalDeviceProperties(physical_device, &physical_device_properties);
-
- VkPhysicalDeviceVulkan12Features vulkan_12_features = {};
- vulkan_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
-
- VkPhysicalDeviceFeatures2 physical_device_features = {};
- physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- physical_device_features.pNext = &vulkan_12_features;
-
- vkGetPhysicalDeviceFeatures2(physical_device, &physical_device_features);
-
- if (vulkan_12_features.bufferDeviceAddress == VK_TRUE &&
- vulkan_12_features.runtimeDescriptorArray == VK_TRUE &&
- vulkan_12_features.shaderStorageImageArrayNonUniformIndexing == VK_TRUE &&
- 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.imagelessFramebuffer == VK_TRUE) {
- std::cerr << "Using physical device " << physical_device_properties.deviceName << std::endl;
- return true;
- }
-
- std::cerr << "Physical device " << physical_device_properties.deviceName << " is missing some features" << std::endl;
- return false;
-}
-
diff --git a/api-test/vk-device.cpp b/src/vk-device.cpp
index 1e7b385..6fa3533 100644
--- a/api-test/vk-device.cpp
+++ b/src/vk-device.cpp
@@ -1,16 +1,22 @@
#include "vk-device.hpp"
-#include <cassert>
-#include <vector>
-
-#include <vulkan/vulkan_core.h>
-
#define VMA_IMPLEMENTATION
#include <vk_mem_alloc.h>
-#include "vk-utils.hpp"
-#include "vulkan-loader.hpp"
-#include "vk-command-buffer.hpp"
+static VkShaderModule create_shader_module(VkDevice device, uint8_t* code, size_t code_size) {
+ VkShaderModule shader_module;
+ VkShaderModuleCreateInfo create_info{
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0U,
+ .codeSize = code_size,
+ .pCode = reinterpret_cast<uint32_t*>(code),
+ };
+
+ VKCHECK(vkCreateShaderModule(device, &create_info, nullptr, &shader_module));
+ return shader_module;
+}
+
vkdevice vkdevice::render_device = vkdevice();
@@ -39,7 +45,7 @@ void vkdevice::init() {
create_memory_allocator();
- bindless = bindless_model::create_bindless_model();
+ bindless.init();
auto semaphore = create_semaphore({
.type = VK_SEMAPHORE_TYPE_TIMELINE,
@@ -50,7 +56,7 @@ void vkdevice::init() {
void vkdevice::deinit() {
vkDeviceWaitIdle(device);
- bindless_model::destroy_bindless_model(bindless);
+ bindless.deinit();
vmaDestroyAllocator(gpu_allocator);
@@ -74,6 +80,8 @@ void vkdevice::wait() { vkDeviceWaitIdle(device); };
handle<device_texture> vkdevice::create_texture(const texture_desc& desc) {
device_texture device_texture;
+ // TODO: This must always be present since we want to display images in ImGui
+ const_cast<texture_desc&>(desc).usages |= VK_IMAGE_USAGE_SAMPLED_BIT;
device_texture.init(desc);
return textures.add(device_texture);
@@ -88,7 +96,9 @@ handle<device_sampler> vkdevice::create_sampler(const sampler_desc& desc) {
handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) {
device_buffer device_buffer{
- .size = desc.size,
+ .size = desc.size,
+ .usages = desc.usages,
+ .name = desc.name,
};
VkBufferCreateInfo create_info{
@@ -118,6 +128,7 @@ handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) {
VmaAllocationInfo alloc_info{};
VKCHECK(vmaCreateBuffer(gpu_allocator, &create_info, &alloc_create_info, &device_buffer.vk_buffer, &device_buffer.alloc, &alloc_info));
+ vmaSetAllocationName(render_device.get_allocator(), device_buffer.alloc, desc.name);
if ((desc.usages & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) != 0U) {
VkBufferDeviceAddressInfo address_info {
@@ -142,7 +153,7 @@ handle<device_pipeline> vkdevice::create_graphics_pipeline(const graphics_pipeli
.pNext = nullptr,
.flags = 0U,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
- .module = create_shader_module(desc.vs_code),
+ .module = create_shader_module(device, desc.vs_code, desc.vs_code_size),
.pName = "main",
.pSpecializationInfo = nullptr,
},
@@ -151,7 +162,7 @@ handle<device_pipeline> vkdevice::create_graphics_pipeline(const graphics_pipeli
.pNext = nullptr,
.flags = 0U,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
- .module = create_shader_module(desc.fs_code),
+ .module = create_shader_module(device, desc.fs_code, desc.fs_code_size),
.pName = "main",
.pSpecializationInfo = nullptr,
},
@@ -259,7 +270,7 @@ handle<device_pipeline> vkdevice::create_graphics_pipeline(const graphics_pipeli
.pDepthStencilState = nullptr,
.pColorBlendState = &color_blend_state_create_info,
.pDynamicState = &dynamic_state_create_info,
- .layout = bindless.graphics_layout,
+ .layout = bindless.global_layout,
.renderPass = nullptr,
.subpass = 0U,
.basePipelineHandle = nullptr,
@@ -296,7 +307,7 @@ handle<device_pipeline> vkdevice::create_compute_pipeline(const compute_pipeline
.pNext = nullptr,
.flags = 0U,
.stage = VK_SHADER_STAGE_COMPUTE_BIT,
- .module = create_shader_module(desc.cs_code),
+ .module = create_shader_module(device, desc.cs_code, desc.cs_code_size),
.pName = "main",
.pSpecializationInfo = nullptr,
};
@@ -306,7 +317,7 @@ handle<device_pipeline> vkdevice::create_compute_pipeline(const compute_pipeline
.pNext = nullptr,
.flags = 0U,
.stage = stage_create_info,
- .layout = bindless.compute_layout,
+ .layout = bindless.global_layout,
.basePipelineHandle = nullptr,
.basePipelineIndex = 0,
};
@@ -517,20 +528,20 @@ void vkdevice::destroy_surface(handle<device_surface> handle) {
// return ret;
// }
-uint64_t vkdevice::submit(command_buffer* buffers, uint32_t count) {
+uint64_t vkdevice::submit(command_buffer* cmd_buffers, uint32_t count) {
assert((max_submitable_command_buffers - count) >= 0);
- const auto queue_type = buffers[0].queue_type;
+ const auto queue_type = cmd_buffers[0].queue_type;
// VkCommandBufferSubmitInfo command_buffers_info[count];
VkCommandBufferSubmitInfo command_buffers_info[max_submitable_command_buffers];
for (auto index{ 0U }; index < count; index++) {
- assert(queue_type == buffers[index].queue_type);
+ assert(queue_type == cmd_buffers[index].queue_type);
auto& command_buffer_info = command_buffers_info[index];
command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO;
command_buffer_info.pNext = nullptr;
- command_buffer_info.commandBuffer = buffers[index].vk_command_buffer;
+ command_buffer_info.commandBuffer = cmd_buffers[index].vk_command_buffer;
command_buffer_info.deviceMask = 0U;
}
@@ -563,25 +574,25 @@ uint64_t vkdevice::submit(command_buffer* buffers, uint32_t count) {
return fence.value;
}
-uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle, command_buffer* buffers, uint32_t count) {
+uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle, command_buffer* cmd_buffers, uint32_t count) {
assert((max_submitable_command_buffers - count) >= 0);
- const auto queue_type = buffers[0].queue_type;
+ const QueueType queue_type = cmd_buffers[0].queue_type;
// VkCommandBufferSubmitInfo command_buffers_info[count];
VkCommandBufferSubmitInfo command_buffers_info[max_submitable_command_buffers];
- for (auto index{ 0U }; index < count; index++) {
- assert(queue_type == buffers[index].queue_type);
+ for (uint32_t index{ 0U }; index < count; index++) {
+ assert(queue_type == cmd_buffers[index].queue_type);
auto& command_buffer_info = command_buffers_info[index];
command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO;
command_buffer_info.pNext = nullptr;
- command_buffer_info.commandBuffer = buffers[index].vk_command_buffer;
+ command_buffer_info.commandBuffer = cmd_buffers[index].vk_command_buffer;
command_buffer_info.deviceMask = 0U;
}
- const auto& surface = get_surface(surface_handle);
- auto& wait = get_semaphore(surface.acquire_semaphores[surface.frame_index]);
+ const device_surface& surface = get_surface(surface_handle);
+ device_semaphore& wait = get_semaphore(surface.acquire_semaphores[surface.frame_index]);
VkSemaphoreSubmitInfo wait_semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.pNext = nullptr,
@@ -630,7 +641,7 @@ uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle,
}
void vkdevice::present(handle<device_surface> surface_handle) {
- auto& surface = vkdevice::get_render_device().get_surface(surface_handle);
+ auto& surface = render_device.get_surface(surface_handle);
VkResult result;
VkPresentInfoKHR present_info{
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
@@ -652,7 +663,7 @@ void vkdevice::present(handle<device_surface> surface_handle) {
}
// private
-void vkdevice::allocate_command_buffers(command_buffer* buffers, size_t count, QueueType type, const char* name) {
+void vkdevice::allocate_command_buffers(command_buffer* cmd_buffers, size_t count, QueueType type, const char* name) {
assert((max_allocable_command_buffers - count) >= 0);
const auto& queue = queues[static_cast<uint32_t>(type)];
VkCommandBuffer command_buffers[max_allocable_command_buffers];
@@ -667,9 +678,9 @@ void vkdevice::allocate_command_buffers(command_buffer* buffers, size_t count, Q
VKCHECK(vkAllocateCommandBuffers(device, &allocate_info, command_buffers));
- for (auto index{ 0U }; index < count; index++) {
- buffers[index].vk_command_buffer = command_buffers[index];
- buffers[index].queue_type = type;
+ for (uint32_t index{ 0U }; index < count; index++) {
+ cmd_buffers[index].vk_command_buffer = command_buffers[index];
+ cmd_buffers[index].queue_type = type;
if (name) {
VkDebugUtilsObjectNameInfoEXT object_name{
@@ -684,21 +695,6 @@ void vkdevice::allocate_command_buffers(command_buffer* buffers, size_t count, Q
}
}
-VkShaderModule vkdevice::create_shader_module(const std::span<uint8_t>& shader_code) {
- VkShaderModule shader_module;
- const auto& code = shader_code;
- VkShaderModuleCreateInfo create_info{
- .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- .pNext = nullptr,
- .flags = 0U,
- .codeSize = code.size(),
- .pCode = reinterpret_cast<uint32_t*>(code.data()),
- };
-
- VKCHECK(vkCreateShaderModule(device, &create_info, nullptr, &shader_module));
- return shader_module;
-}
-
void vkdevice::create_swapchain(const surface_desc& desc, device_surface& surface) {
VkSurfaceKHR vk_surface = surface.vk_surface;
@@ -808,6 +804,7 @@ void vkdevice::create_swapchain(const surface_desc& desc, device_surface& surfac
.format = desc.surface_format.format,
.type = VK_IMAGE_TYPE_2D,
.vk_image = images[index],
+ .name = "swapchain image"
});
}
}
@@ -932,10 +929,15 @@ void vkdevice::create_device() {
}
void vkdevice::create_memory_allocator() {
+ VmaVulkanFunctions functions = {
+ .vkGetInstanceProcAddr = vkGetInstanceProcAddr,
+ .vkGetDeviceProcAddr = vkGetDeviceProcAddr,
+ };
VmaAllocatorCreateInfo create_info{
.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT,
.physicalDevice = physical_device,
.device = device,
+ .pVulkanFunctions = &functions,
.instance = instance,
.vulkanApiVersion = VK_API_VERSION_1_2,
};
@@ -966,9 +968,15 @@ void vkdevice::pick_physical_device() {
std::vector<VkPhysicalDevice> physical_devices{ physical_devices_count };
vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data());
+ physical_device_props = VkPhysicalDeviceProperties2 {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
+ .pNext = nullptr,
+ };
+
for (auto& physical_dev : physical_devices) {
if (device_support_features(physical_dev)) {
physical_device = physical_dev;
+
return;
}
}
@@ -979,13 +987,9 @@ void vkdevice::pick_physical_device() {
bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) {
// limits
{
- VkPhysicalDeviceProperties2 props{
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
- .pNext = nullptr,
- };
- vkGetPhysicalDeviceProperties2(physical_dev, &props);
+ vkGetPhysicalDeviceProperties2(physical_dev, &physical_device_props);
- VkPhysicalDeviceLimits* limits = &props.properties.limits;
+ VkPhysicalDeviceLimits* limits = &physical_device_props.properties.limits;
if (limits->maxPerStageDescriptorSampledImages < 0x10000 ||
limits->maxPerStageDescriptorStorageImages < 0x10000 ||
limits->maxDescriptorSetSampledImages < 0x10000 ||
@@ -1024,6 +1028,7 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) {
{
VkPhysicalDeviceVulkan13Features vulkan_13_features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
+ .pNext = nullptr,
};
VkPhysicalDeviceFeatures2 physical_device_features{
@@ -1067,7 +1072,7 @@ idlist<> device_texture::storage_indices = {};
idlist<> device_sampler::sampler_indices = {};
void device_texture::init(const texture_desc& desc) {
- auto& render_device = vkdevice::get_render_device();
+ auto& render_device = vkdevice::get();
const auto& bindless = render_device.get_bindingmodel();
auto* device = render_device.get_device();
@@ -1076,6 +1081,7 @@ void device_texture::init(const texture_desc& desc) {
width = desc.width;
height = desc.height;
mips = desc.mips;
+ name = desc.name;
aspects = ((desc.usages & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0U)
? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT
: VK_IMAGE_ASPECT_COLOR_BIT;
@@ -1116,6 +1122,7 @@ void device_texture::init(const texture_desc& desc) {
};
VKCHECK(vmaCreateImage(render_device.get_allocator(), &create_info, &alloc_create_info, &vk_image, &alloc, nullptr));
+ vmaSetAllocationName(render_device.get_allocator(), alloc, desc.name);
}
if (desc.name) {
@@ -1147,7 +1154,8 @@ void device_texture::init(const texture_desc& desc) {
write_descriptor_sets.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
- .dstSet = bindless.sets[BindlessSetType::GLOBAL],
+ // .dstSet = bindless.sets[BindlessSetType::GLOBAL],
+ .dstSet = bindless.global_set,
.dstBinding = 2U,
.dstArrayElement = storage_index.id,
.descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo),
@@ -1163,7 +1171,8 @@ void device_texture::init(const texture_desc& desc) {
write_descriptor_sets.push_back({
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
- .dstSet = bindless.sets[BindlessSetType::GLOBAL],
+ // .dstSet = bindless.sets[BindlessSetType::GLOBAL],
+ .dstSet = bindless.global_set,
.dstBinding = 1U,
.dstArrayElement = sampled_index.id,
.descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo),
@@ -1178,7 +1187,7 @@ void device_texture::init(const texture_desc& desc) {
}
void device_texture::release() {
- auto& render_device = vkdevice::get_render_device();
+ auto& render_device = vkdevice::get();
auto* device = render_device.get_device();
auto* gpu_allocator = render_device.get_allocator();
@@ -1203,7 +1212,7 @@ void device_texture::release() {
}
void device_texture::create_views() {
- auto* device = vkdevice::get_render_device().get_device();
+ auto* device = vkdevice::get().get_device();
VkImageViewCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@@ -1239,7 +1248,7 @@ void device_texture::create_views() {
void device_sampler::init(const sampler_desc& desc) {
- auto& render_device = vkdevice::get_render_device();
+ auto& render_device = vkdevice::get();
// const auto& bindless = render_device.get_bindingmodel();
auto* device = render_device.get_device();
diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp
deleted file mode 100644
index ddff268..0000000
--- a/src/vk-renderer.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-#include "vk-renderer.hpp"
-
-#include <cstring>
-#include <cassert>
-
-#include <vk_mem_alloc.h>
-
-#include "vulkan-loader.hpp"
-
-#include "compute-renderpass.hpp"
-#include "primitive-renderpass.hpp"
-
-#include "texture.hpp"
-
-#include "window.hpp"
-
-#ifdef _DEBUG
-#define VKRESULT(result) assert(result == VK_SUCCESS);
-#else
-#define VKRESULT(result) result;
-#endif
-
-auto vkrenderer::context = vkcontext();
-auto vkrenderer::api = vkapi(vkrenderer::context);
-auto vkrenderer::upload_queue = std::vector<Texture*>();
-
-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_NULL_HANDLE
- );
-
- swapchain_textures.resize(swapchain.image_count);
- for (size_t index = 0; index < swapchain.image_count; index++) {
- swapchain_textures[index] = new Texture(swapchain.images[index]);
- }
-
- tonemapping_pipeline = api.create_compute_pipeline("tonemapping");
-
- graphics_command_pool = api.create_command_pool();
- api.allocate_command_buffers(graphics_command_pool, graphics_command_buffers, virtual_frames_count);
-
- for(size_t index { 0 }; index < virtual_frames_count; index++) {
- submission_fences[index] = api.create_fence();
- execution_semaphores[index] = api.create_semaphore();
- acquire_semaphores[index] = api.create_semaphore();
-
- copy_command_pools[index] = api.create_command_pool();
- api.allocate_command_buffers(copy_command_pools[index], &copy_command_buffers[index], 1);
-
- // staging_buffers[index] = create_staging_buffer(4096 * 4096 * sizeof(uint32_t));
- staging_buffers[index] = new RingBuffer(4096ULL * 4096ULL * sizeof(uint32_t));
- }
-}
-
-vkrenderer::~vkrenderer() {
- VKRESULT(vkWaitForFences(context.device, virtual_frames_count, submission_fences, VK_TRUE, UINT64_MAX))
-
- for (auto& renderpass : renderpasses) {
- delete renderpass;
- }
-
- for(size_t index { 0 }; index < virtual_frames_count; index++) {
- vkFreeCommandBuffers(context.device, copy_command_pools[index], 1, &copy_command_buffers[index]);
- vkDestroyCommandPool(context.device, copy_command_pools[index], nullptr);
- }
-
- api.destroy_fences(submission_fences, virtual_frames_count);
- api.destroy_semaphores(execution_semaphores, virtual_frames_count);
- api.destroy_semaphores(acquire_semaphores, virtual_frames_count);
-
- vkFreeCommandBuffers(context.device, graphics_command_pool, virtual_frames_count, graphics_command_buffers);
- vkDestroyCommandPool(context.device, graphics_command_pool, nullptr);
-
-
- api.destroy_pipeline(tonemapping_pipeline);
-
- api.destroy_swapchain(swapchain);
- api.destroy_surface(platform_surface);
-}
-void vkrenderer::recreate_swapchain() {
- VKRESULT(vkWaitForFences(context.device, vkrenderer::virtual_frames_count, submission_fences, 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,
- swapchain_image_usages,
- old_swapchain.handle
- );
-
- api.destroy_swapchain(old_swapchain);
-
- swapchain_textures.resize(swapchain.image_count);
- for (size_t index = 0; index < swapchain.image_count; index++) {
- swapchain_textures[index] = new Texture(swapchain.images[index]);
- }
-}
-
-void vkrenderer::queue_image_update(Texture* texture) {
- upload_queue.push_back(texture);
-}
-
-void vkrenderer::update_images() {
- if(upload_queue.empty())
- return;
-
- auto* staging_buffer = staging_buffers[virtual_frame_index];
- staging_buffer->reset();
-
- VkCommandBuffer command_buffer = copy_command_buffers[virtual_frame_index];
- vkrenderer::api.start_record(command_buffer);
-
- while(!upload_queue.empty()) {
- auto* texture = upload_queue.back();
- auto texture_size = texture->size();
- auto offset = staging_buffer->alloc(texture_size);
-
- if (offset == RingBuffer::invalid_alloc)
- break;
-
- upload_queue.pop_back();
-
- staging_buffer->write(texture->data, offset, texture_size);
-
- vkrenderer::api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, texture->device_image);
- vkrenderer::api.copy_buffer(command_buffer, staging_buffer->device_buffer, texture->device_image, 0, offset);
- vkrenderer::api.image_barrier(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, texture->device_image);
- }
-
- vkrenderer::api.end_record(command_buffer);
-
- recorded_command_buffers.push_back(command_buffer);
-}
-
-Buffer* vkrenderer::create_buffer(size_t size) {
- return new Buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
-}
-
-Buffer* vkrenderer::create_index_buffer(size_t size) {
- return new Buffer(size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
-}
-
-Buffer* vkrenderer::create_staging_buffer(size_t size) {
- return new Buffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
-}
-
-Texture* vkrenderer::create_2d_texture(size_t width, size_t height, VkFormat format, Sampler *sampler) {
- return new Texture(width, height, 1, format, sampler);
-}
-
-// TODO: Check if a similar sampler has been allocated
-Sampler* vkrenderer::create_sampler(VkFilter filter, VkSamplerAddressMode address_mode) {
- auto* sampler = new Sampler();
-
- sampler->device_sampler = api.create_sampler(filter, address_mode);
-
- return sampler;
-}
-
-ComputeRenderpass* vkrenderer::create_compute_renderpass() {
- renderpasses.push_back(new ComputeRenderpass(api));
-
- 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(primitive_render_pass);
-}
-
-void vkrenderer::render() {
- swapchain_image_index = 0;
- auto acquire_result = vkAcquireNextImageKHR(context.device, swapchain.handle, UINT64_MAX, acquire_semaphores[virtual_frame_index], VK_NULL_HANDLE, &swapchain_image_index);
- handle_swapchain_result(acquire_result);
-
- api.start_record(graphics_command_buffers[virtual_frame_index]);
-
- auto* cmd_buf = graphics_command_buffers[virtual_frame_index];
-
- // wait for transfer operations
-
- 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_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.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]);
-
- api.end_record(cmd_buf);
-
- recorded_command_buffers.push_back(cmd_buf);
-}
-
-void vkrenderer::begin_frame() {
- recorded_command_buffers.clear();
-
- VKRESULT(vkWaitForFences(context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX))
- VKRESULT(vkResetFences(context.device, 1, &submission_fences[virtual_frame_index]))
-
- update_images();
-}
-
-void vkrenderer::finish_frame() {
- api.submit(recorded_command_buffers.data(), recorded_command_buffers.size(), acquire_semaphores[virtual_frame_index], execution_semaphores[virtual_frame_index], submission_fences[virtual_frame_index]);
-
- auto present_result = api.present(swapchain, swapchain_image_index, execution_semaphores[virtual_frame_index]);
- handle_swapchain_result(present_result);
-
- virtual_frame_index = ++virtual_frame_index % virtual_frames_count;
-}
-
-
-
-// private functions
-void vkrenderer::handle_swapchain_result(VkResult function_result) {
- switch(function_result) {
- case VK_ERROR_OUT_OF_DATE_KHR:
- return recreate_swapchain();
- case VK_ERROR_SURFACE_LOST_KHR:
- assert(true && "surface lost");
- default:
- return;
- }
-}
-
-
-
-Buffer::Buffer(size_t size, VkBufferUsageFlagBits usage)
- : buffer_size(size), usage(usage) {
- device_buffer = vkrenderer::api.create_buffer(size, usage, VMA_MEMORY_USAGE_CPU_TO_GPU);
-}
-
-Buffer::~Buffer() {
- vkrenderer::api.destroy_buffer(device_buffer);
-}
-
-void Buffer::write(void* data, off_t alloc_offset, size_t data_size) const {
- auto api_buffer = vkrenderer::api.get_buffer(device_buffer);
-
- std::memcpy((uint8_t*)api_buffer.device_ptr + alloc_offset, data, data_size);
-}
-
-void Buffer::resize(size_t new_size) {
- auto old_device_buffer = device_buffer;
- new_size = static_cast<uint32_t>(exp2(ceil(log2((double)new_size))));
-
- device_buffer = vkrenderer::api.create_buffer(new_size, usage, VMA_MEMORY_USAGE_CPU_TO_GPU);
-
- auto old_buffer = vkrenderer::api.get_buffer(device_buffer);
- auto new_buffer = vkrenderer::api.get_buffer(device_buffer);
- std::memcpy(new_buffer.device_ptr, old_buffer.device_ptr, buffer_size);
-
- buffer_size = new_size;
-
- vkrenderer::api.destroy_buffer(old_device_buffer);
-}
-
-
-RingBuffer::RingBuffer(size_t size)
- : buffer_size(size) {
- device_buffer = vkrenderer::api.create_buffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
- }
diff --git a/api-test/vk-utils.cpp b/src/vk-utils.cpp
index 4df6424..89f5741 100644
--- a/api-test/vk-utils.cpp
+++ b/src/vk-utils.cpp
@@ -1,7 +1,5 @@
#include "vk-utils.hpp"
-#include <cstdio>
-
VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT type,
const VkDebugUtilsMessengerCallbackDataEXT* data,