diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 1053 |
1 files changed, 728 insertions, 325 deletions
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; } |
