diff options
| author | ladevieq <ladevie.quentin@gmail.com> | 2026-08-17 02:20:13 +0200 |
|---|---|---|
| committer | ladevieq <ladevie.quentin@gmail.com> | 2026-08-17 02:20:13 +0200 |
| commit | 782741f0fea5b2a95aed9ad3673ecafb4b164885 (patch) | |
| tree | 7e381783dc52fc54eba8d4850b05ea759c5eab11 | |
| parent | 92e09dc06f8c8dd5b7a9323d586f4bf642078727 (diff) | |
Inital work on vulkan descriptor heap implementation
| -rw-r--r-- | include/vk-bindless.hpp | 2 | ||||
| -rw-r--r-- | include/vk-command-buffer.hpp | 11 | ||||
| -rw-r--r-- | include/vk-device-types.hpp | 21 | ||||
| -rw-r--r-- | include/vk-device.hpp | 67 | ||||
| -rw-r--r-- | include/vulkan-loader.hpp | 6 | ||||
| -rw-r--r-- | src/main.cpp | 184 | ||||
| -rw-r--r-- | src/vk-bindless.cpp | 8 | ||||
| -rw-r--r-- | src/vk-command-buffer.cpp | 150 | ||||
| -rw-r--r-- | src/vk-device.cpp | 665 |
9 files changed, 549 insertions, 565 deletions
diff --git a/include/vk-bindless.hpp b/include/vk-bindless.hpp index 008e420..be076b8 100644 --- a/include/vk-bindless.hpp +++ b/include/vk-bindless.hpp @@ -20,7 +20,7 @@ enum SamplerType : uint32_t { struct device_buffer; struct bindless_model { - [[nodiscard]] device_buffer& get_uniform_buffer(enum UniformTypes type) const; + [[nodiscard]] device_buffer* get_uniform_buffer(enum UniformTypes type) const; void init(); diff --git a/include/vk-command-buffer.hpp b/include/vk-command-buffer.hpp index 82d5439..f82e52f 100644 --- a/include/vk-command-buffer.hpp +++ b/include/vk-command-buffer.hpp @@ -25,7 +25,8 @@ private: public: rect render_area; - std::span<handle<device_texture>> color_attachments; + handle<device_texture>* color_attachments; + size_t color_attachments_count; }; struct draw_params { @@ -55,15 +56,17 @@ struct command_buffer { VkCommandBuffer vk_command_buffer; QueueType queue_type; + + // TODO: Add relevant fields in order to bind heaps }; // General purpose queue struct graphics_command_buffer: public command_buffer { - void dispatch(const dispatch_params& params) const; + void dispatch(const dispatch_params& params, const void* data, size_t size) const; void begin_renderpass(const renderpass_params& params) const; - void draw(const draw_params& params) const; - void draw_indexed(const draw_indexed_params& params) const; + void draw(const draw_params& params, const void* data, size_t size) const; + void draw_indexed(const draw_indexed_params& params, const void* data, size_t size) const; void end_renderpass() const; }; diff --git a/include/vk-device-types.hpp b/include/vk-device-types.hpp index f77d2af..25f933f 100644 --- a/include/vk-device-types.hpp +++ b/include/vk-device-types.hpp @@ -160,7 +160,8 @@ struct graphics_pipeline_desc { size_t vs_code_size; uint8_t* fs_code; size_t fs_code_size; - std::span<VkFormat> color_attachments_format; + VkFormat* color_attachments_format; + size_t color_attachments_format_count; VkFormat depth_attachment_format; VkFormat stencil_attachment_format; const char* name; @@ -202,17 +203,17 @@ struct surface_desc { }; struct device_surface { - VkSurfaceKHR vk_surface; - VkSwapchainKHR vk_swapchain; - VkSurfaceFormatKHR surface_format; + VkSurfaceKHR vk_surface; + VkSwapchainKHR vk_swapchain; + VkSurfaceFormatKHR surface_format; - handle<device_texture> swapchain_images[surface_desc::max_image_count]; - uint32_t image_index; - uint32_t image_count; - uint32_t frame_index = 0U; + handle<device_texture> swapchain_images[surface_desc::max_image_count]; + uint32_t image_index; + uint32_t image_count; + uint32_t frame_index = 0U; - handle<device_semaphore> acquire_semaphores[surface_desc::max_image_count]; - handle<device_semaphore> submit_semaphores[surface_desc::max_image_count]; + device_semaphore acquire_semaphores[surface_desc::max_image_count]; + device_semaphore submit_semaphores[surface_desc::max_image_count]; uint32_t acquire_image_index(); }; diff --git a/include/vk-device.hpp b/include/vk-device.hpp index e2e8c99..84a1a36 100644 --- a/include/vk-device.hpp +++ b/include/vk-device.hpp @@ -37,8 +37,6 @@ class vkdevice { handle<device_surface> create_surface(const surface_desc& desc); - handle<device_semaphore> create_semaphore(const semaphore_desc& desc, const char* name); - void destroy_texture(handle<device_texture> handle); void destroy_sampler(handle<device_sampler> handle); @@ -47,8 +45,6 @@ class vkdevice { void destroy_pipeline(handle<device_pipeline> handle); - void destroy_semaphore(handle<device_semaphore> handle); - void destroy_surface(handle<device_surface> handle); template<typename buffer_type> @@ -56,50 +52,34 @@ class vkdevice { allocate_command_buffers(static_cast<command_buffer*>(buffers), count, queue_type, name); } - [[nodiscard]] inline device_texture& get_texture(handle<device_texture> handle) { - return textures[handle]; - } - - [[nodiscard]] inline device_sampler& get_sampler(handle<device_sampler> handle) { - return samplers[handle]; - } - - [[nodiscard]] inline device_buffer& get_buffer(handle<device_buffer> handle) { - return buffers[handle]; + [[nodiscard]] inline device_texture* get_texture(handle<device_texture> handle) { + return &textures[handle]; } - [[nodiscard]] inline const device_pipeline& get_pipeline(handle<device_pipeline> handle) const { - return pipelines[handle]; + [[nodiscard]] inline device_sampler* get_sampler(handle<device_sampler> handle) { + return &samplers[handle]; } - [[nodiscard]] inline device_surface& get_surface(handle<device_surface> handle) { - return surfaces[handle]; + [[nodiscard]] inline device_buffer* get_buffer(handle<device_buffer> handle) { + return &buffers[handle]; } - [[nodiscard]] inline device_semaphore& get_semaphore(handle<device_semaphore> handle) { - return semaphores[handle]; + [[nodiscard]] inline const device_pipeline* get_pipeline(handle<device_pipeline> handle) const { + return &pipelines[handle]; } - [[nodiscard]] inline const bindless_model& get_bindingmodel() const { - return bindless; + [[nodiscard]] inline device_surface* get_surface(handle<device_surface> handle) { + return &surfaces[handle]; } - const freelist<device_texture>& get_textures() const { - return textures; + inline VmaAllocator get_allocator() const { + return gpu_allocator; } inline VkDevice get_device() const { return device; } - inline VmaAllocator get_allocator() { - 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); @@ -109,6 +89,8 @@ class vkdevice { void wait(); + void wait_for_fence(u64 value); + private: vkdevice() = default; ~vkdevice() = default; @@ -122,16 +104,10 @@ class vkdevice { void create_device(); - void create_memory_allocator(); - - void create_command_pools(); - - void pick_physical_device(); + void create_heaps(VkPhysicalDeviceDescriptorHeapPropertiesEXT& descriptor_heap_props); bool device_support_features(VkPhysicalDevice physical_dev); - void create_debug_layer_callback(); - queue queues[static_cast<uint32_t>(QueueType::MAX)]; VkInstance instance; @@ -139,9 +115,15 @@ class vkdevice { VkPhysicalDeviceProperties2 physical_device_props; VkDevice device; - VmaAllocator gpu_allocator; + handle<device_buffer> image_heap; // TODO: Dont use handle for internally used resources + handle<device_buffer> sampler_heap; + + static constexpr size_t max_images_count = UINT16_MAX; + static constexpr size_t max_samplers_count = 16U; - bindless_model bindless; + static size_t + + VmaAllocator gpu_allocator; static constexpr size_t max_allocable_command_buffers = 16; static constexpr size_t max_submitable_command_buffers = 16; @@ -151,9 +133,8 @@ class vkdevice { freelist<device_buffer> buffers; freelist<device_pipeline> pipelines; freelist<device_surface> surfaces; - freelist<device_semaphore> semaphores; - device_semaphore timeline_semaphore; + device_semaphore fence; static vkdevice render_device; diff --git a/include/vulkan-loader.hpp b/include/vulkan-loader.hpp index 7a3a68e..3d9237b 100644 --- a/include/vulkan-loader.hpp +++ b/include/vulkan-loader.hpp @@ -5,6 +5,7 @@ #if _WIN32 #include <vulkan/vulkan_core.h> +#define VULKAN_H_ 1 // Fake vulkan.h include typedef unsigned long DWORD; typedef const wchar_t* LPCWSTR; typedef void* HANDLE; @@ -90,6 +91,7 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; X(vkCmdPipelineBarrier) \ X(vkCmdPipelineBarrier2) \ X(vkCmdPushConstants) \ + X(vkCmdPushDataEXT) \ X(vkCmdClearColorImage) \ X(vkCmdBeginRenderPass) \ X(vkCmdBeginRendering) \ @@ -97,6 +99,8 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; X(vkCmdBindVertexBuffers) \ X(vkCmdBindIndexBuffer) \ X(vkCmdBindDescriptorSets) \ + X(vkCmdBindResourceHeapEXT) \ + X(vkCmdBindSamplerHeapEXT) \ X(vkCmdSetViewport) \ X(vkCmdSetScissor) \ X(vkCmdCopyBuffer) \ @@ -125,6 +129,8 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES; X(vkCreateDescriptorPool) \ X(vkAllocateDescriptorSets) \ X(vkUpdateDescriptorSets) \ + X(vkWriteResourceDescriptorsEXT) \ + X(vkWriteSamplerDescriptorsEXT) \ X(vkGetBufferDeviceAddress) \ X(vkGetBufferMemoryRequirements) \ X(vkGetImageMemoryRequirements) \ diff --git a/src/main.cpp b/src/main.cpp index 74bb655..3cb56dc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,7 @@ // windows.h stuff // =============== #if defined(_WIN32) - #if defined(_M_AMD64) + #if defined(_M_AMD64) || defined(_M_X64) #define _AMD64_ #endif #include <basetsd.h> @@ -21,24 +21,17 @@ // ------------------- // thirdparties // ------------------- -#define IMGUI_DISABLE_WIN32_FUNCTIONS -#include "imgui.cpp" -#include "imgui_draw.cpp" -#include "imgui_tables.cpp" -#include "imgui_widgets.cpp" +#include "imgui.h" -#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> - #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 @@ -120,10 +113,10 @@ void ui(scene* scene, float frame_time) { 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; + 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)); + ImGui::Image(tex->get_sampled_index(), ImVec2(128, 128)); } } @@ -221,7 +214,7 @@ int main() { #endif .image_count = 2U, }); - const device_surface& surface = device.get_surface(surface_handle); + const device_surface* surface = device.get_surface(surface_handle); // ============== @@ -230,7 +223,7 @@ int main() { const handle<device_buffer> staging_buffer_handle = device.create_buffer({ .size = 128 * MB, #if VK - .usages = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .usages = VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, #else @@ -240,12 +233,12 @@ int main() { .heap_type = D3D12_HEAP_TYPE_UPLOAD, #endif }); - const device_buffer& staging_buffer = device.get_buffer(staging_buffer_handle); + const device_buffer* staging_buffer = device.get_buffer(staging_buffer_handle); 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, + .usages = VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, #else @@ -255,15 +248,15 @@ int main() { 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, + .usages = VK_BUFFER_USAGE_2_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_INDEX_BUFFER_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, #else #endif }); - device_buffer vertex_buffer = device.get_buffer(vertex_buffer_handle); - device_buffer index_buffer = device.get_buffer(index_buffer_handle); + device_buffer* vertex_buffer = device.get_buffer(vertex_buffer_handle); + device_buffer* index_buffer = device.get_buffer(index_buffer_handle); // ================ @@ -290,7 +283,7 @@ int main() { .cs_code_size = tonemapping_code_size, }); - std::array<VkFormat, 1U> formats { surface.surface_format.format }; + 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; @@ -300,7 +293,8 @@ int main() { .vs_code_size = vertex_code_size, .fs_code = fragment_code, .fs_code_size = fragment_code_size, - .color_attachments_format = formats + .color_attachments_format = formats.data(), + .color_attachments_format_count = formats.size() }); size_t transmittance_lut_code_size = 0U; @@ -320,12 +314,12 @@ int main() { 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); + 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); + auto* addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer->mapped_ptr) + buffer_offset); memcpy(addr, data, size); u8 *pixels = nullptr; @@ -335,7 +329,7 @@ int main() { 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); + addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer->mapped_ptr) + ui_offset); memcpy(addr, pixels, size); @@ -450,15 +444,15 @@ int main() { }); #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(); + 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 - const device_texture& ui_texture = device.get_texture(ui_texture_handle); - const device_texture& transmittance_lut = device.get_texture(transmittance_lut_handle); + 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); - io.Fonts->SetTexID(reinterpret_cast<void*>(static_cast<uintptr_t>(ui_texture.get_sampled_index()))); + io.Fonts->SetTexID(reinterpret_cast<void*>(static_cast<uintptr_t>(ui_texture->get_sampled_index()))); #if VK @@ -491,23 +485,28 @@ int main() { { - device_buffer& draws_uniform_buffer = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW); + // 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(); + // } *params = draws_uniform_buffer->allocate<struct params>(); + } 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(); + 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(); 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 }}, - }); + }, + ¶ms, sizeof(struct params)); } { @@ -516,16 +515,21 @@ int main() { 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; + // } *params = draws_uniform_buffer->allocate<struct params>(); + } params; + // params->lut_id = transmittance_lut->get_storage_index(); + // params->width = transmittance_lut->width; + // params->height = transmittance_lut->height; + params.lut_id = transmittance_lut->get_storage_index(); + params.width = transmittance_lut->width; + params.height = transmittance_lut->height; graphics_command_buffers[0].dispatch({ .pipeline = transmittance_lut_compute, .group_size = { .vec = { 1024U, 1024U, 1U }}, .local_group_size = { .vec { 8U, 8U, 1U }}, - }); + }, + ¶ms, sizeof(struct params)); } } @@ -651,12 +655,12 @@ int main() { ImDrawList* cmd_list = draw_data->CmdLists[index]; size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size(); - u8* vtx_ptr = static_cast<uint8_t*>(vertex_buffer.mapped_ptr) + vertex_offset; + 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); 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); + 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); } } @@ -665,12 +669,12 @@ int main() { // 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)); + // 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)]; + auto backbuffer = surface->swapchain_images[device.acquire_image_index(surface_handle)]; color_attachment[0] = backbuffer; // RD_START_CAPTURE; @@ -698,37 +702,49 @@ int main() { 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; + // 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; + struct params uniforms = {}; + 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, } }, - }); + }, (const void*)&uniforms, sizeof(struct params)); } { struct params { u32 output_id; u32 accumulation_id; - } *uniforms = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW).allocate<params>(); + // } *uniforms = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW)->allocate<params>(); + } uniforms; // 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; + // uniforms->output_id = device.get_texture(backbuffer)->get_storage_index(); + // uniforms->accumulation_id = (virtual_frame_index == 0U) ? result_storage_index : acc_storage_index; + 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, } }, - }); + }, &uniforms, sizeof(struct params)); } } @@ -741,10 +757,11 @@ int main() { .width = static_cast<uint32_t>(draw_data->DisplaySize.x), .height = static_cast<uint32_t>(draw_data->DisplaySize.y), }, - .color_attachments = color_attachment, + .color_attachments = color_attachment.data(), + .color_attachments_count = color_attachment.size(), }); - auto& draws_uniform_buffer = device.get_bindingmodel().get_uniform_buffer(UniformTypes::DRAW); + // device_buffer* 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++) { @@ -752,28 +769,27 @@ int main() { 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), - }; - } + 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{ + struct 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, @@ -782,7 +798,7 @@ int main() { .vertex_offset = draw_command.VtxOffset + vertex_offset, .index_offset = draw_command.IdxOffset + index_offset, .instance_count = 1U, - }); + }, &ui_param, sizeof(ui_param)); } vertex_offset += cmd_list->VtxBuffer.size(); index_offset += cmd_list->IdxBuffer.size(); diff --git a/src/vk-bindless.cpp b/src/vk-bindless.cpp index 9e517df..8f29834 100644 --- a/src/vk-bindless.cpp +++ b/src/vk-bindless.cpp @@ -3,7 +3,7 @@ #include "vk-device.hpp" #include "vk-utils.hpp" -device_buffer& bindless_model::get_uniform_buffer(enum UniformTypes type) const { +device_buffer* bindless_model::get_uniform_buffer(enum UniformTypes type) const { return vkdevice::get().get_buffer(uniform_buffers[type]); } @@ -185,7 +185,7 @@ void bindless_model::init() { { uniform_buffers[UniformTypes::GLOBAL] = render_device.create_buffer({ .size = globals_uniform_buffer_size, - .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .usages = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, .name = "global uniform buffer", @@ -198,7 +198,7 @@ void bindless_model::init() { { uniform_buffers[UniformTypes::PASS] = render_device.create_buffer({ .size = passes_uniform_buffer_size, - .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .usages = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, .name = "passes uniform buffer" @@ -211,7 +211,7 @@ void bindless_model::init() { { uniform_buffers[UniformTypes::DRAW] = render_device.create_buffer({ .size = draws_uniform_buffer_size, - .usages = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + .usages = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, .name = "draws uniform buffer", diff --git a/src/vk-command-buffer.cpp b/src/vk-command-buffer.cpp index 26c2d03..e16e384 100644 --- a/src/vk-command-buffer.cpp +++ b/src/vk-command-buffer.cpp @@ -12,16 +12,20 @@ void command_buffer::start() const { VKCHECK(vkBeginCommandBuffer(vk_command_buffer, &begin_info)); - 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; + // TODO: Bind heaps + VkBindHeapInfoEXT image_bind_heap_info = { + .sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT, + .pNext = nullptr, + }; - if (queue_type == QueueType::GRAPHICS) { - 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.global_layout, 0, 1U, &bindless.global_set, 0U, nullptr); - } + vkCmdBindResourceHeapEXT(vk_command_buffer, &image_bind_heap_info); + + VkBindHeapInfoEXT sampler_bind_heap_info = { + .sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT, + .pNext = nullptr, + }; + + vkCmdBindSamplerHeapEXT(vk_command_buffer, &sampler_bind_heap_info); } void command_buffer::stop() const { @@ -29,10 +33,10 @@ 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().get_texture(texture_handle); + device_texture* texture = vkdevice::get().get_texture(texture_handle); VkImageSubresourceRange subresource_range{ - .aspectMask = texture.aspects, + .aspectMask = texture->aspects, .baseMipLevel = 0U, .levelCount = 1U, .baseArrayLayer = 0U, @@ -42,15 +46,15 @@ void command_buffer::barrier(handle<device_texture> texture_handle, VkPipelineSt VkImageMemoryBarrier2 image_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, - .srcStageMask = texture.stage, - .srcAccessMask = texture.access, + .srcStageMask = texture->stage, + .srcAccessMask = texture->access, .dstStageMask = stage, .dstAccessMask = access, - .oldLayout = texture.layout, + .oldLayout = texture->layout, .newLayout = layout, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture.vk_image, + .image = texture->vk_image, .subresourceRange = subresource_range, }; @@ -67,18 +71,18 @@ void command_buffer::barrier(handle<device_texture> texture_handle, VkPipelineSt }; vkCmdPipelineBarrier2(vk_command_buffer, &dependency_info); - texture.layout = layout; - texture.stage = stage; - texture.access = access; + texture->layout = layout; + texture->stage = stage; + texture->access = access; } void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_texture> texture_handle, uint64_t offset) const { - auto& device = vkdevice::get(); - const auto& buffer = device.get_buffer(buffer_handle); - const auto& texture = device.get_texture(texture_handle); + auto& device = vkdevice::get(); + const device_buffer* buffer = device.get_buffer(buffer_handle); + const device_texture* texture = device.get_texture(texture_handle); VkImageSubresourceLayers image_subresource_layers{ - .aspectMask = texture.aspects, + .aspectMask = texture->aspects, .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1, @@ -91,24 +95,34 @@ void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_t .imageSubresource = image_subresource_layers, .imageOffset = { .x = 0, .y = 0, .z = 0 }, .imageExtent = { - .width = texture.width, - .height = texture.height, - .depth = texture.depth, + .width = texture->width, + .height = texture->height, + .depth = texture->depth, }, }; - vkCmdCopyBufferToImage(vk_command_buffer, buffer.vk_buffer, texture.vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_to_image_copy); + vkCmdCopyBufferToImage(vk_command_buffer, buffer->vk_buffer, texture->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_to_image_copy); } -void graphics_command_buffer::dispatch(const dispatch_params& params) const { - const device_pipeline& pipeline = vkdevice::get().get_pipeline(params.pipeline); - const bindless_model& bindless = vkdevice::get().get_bindingmodel(); +void graphics_command_buffer::dispatch(const dispatch_params& params, const void* data, size_t size) const { + 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); + 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); + // 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); + VkPushDataInfoEXT push_data { + .sType = VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT, + .pNext = nullptr, + .offset = 0, + .data = { + .address = data, + .size = size, + } + }; + vkCmdPushDataEXT(vk_command_buffer, &push_data); 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; @@ -117,16 +131,16 @@ void graphics_command_buffer::dispatch(const dispatch_params& params) const { } void graphics_command_buffer::begin_renderpass(const renderpass_params& params) const { - std::vector<VkRenderingAttachmentInfo> attachments_info(params.color_attachments.size()); + std::vector<VkRenderingAttachmentInfo> attachments_info(params.color_attachments_count); - for (auto index{ 0U }; index < params.color_attachments.size(); index++) { + for (auto index{ 0U }; index < params.color_attachments_count; index++) { auto& attachment_info = attachments_info[index]; - auto& attachment = vkdevice::get().get_texture(params.color_attachments[index]); + device_texture* attachment = vkdevice::get().get_texture(params.color_attachments[index]); attachment_info.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; attachment_info.pNext = nullptr; - attachment_info.imageView = attachment.whole_view; - attachment_info.imageLayout = attachment.layout; + attachment_info.imageView = attachment->whole_view; + attachment_info.imageLayout = attachment->layout; attachment_info.resolveMode = VK_RESOLVE_MODE_NONE; attachment_info.resolveImageView = nullptr; attachment_info.resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -171,43 +185,65 @@ 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; + // 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); } -void graphics_command_buffer::draw(const draw_params& params) const { +void graphics_command_buffer::draw(const draw_params& params, const void* data, size_t size) const { auto& device = vkdevice::get(); - const auto& pipeline = device.get_pipeline(params.pipeline); + const device_pipeline* pipeline = device.get_pipeline(params.pipeline); + + // const auto& bindless = device.get_bindingmodel(); - const auto& bindless = device.get_bindingmodel(); + vkCmdBindPipeline(vk_command_buffer, pipeline->bind_point, pipeline->vk_pipeline); - 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); - 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); + VkPushDataInfoEXT push_data { + .sType = VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT, + .pNext = nullptr, + .offset = 0, + .data = { + .address = data, + .size = size, + } + }; + vkCmdPushDataEXT(vk_command_buffer, &push_data); 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 { +void graphics_command_buffer::draw_indexed(const draw_indexed_params& params, const void* data, size_t size) const { auto& device = vkdevice::get(); - const auto& pipeline = device.get_pipeline(params.pipeline); + const device_pipeline* pipeline = device.get_pipeline(params.pipeline); - const auto& bindless = device.get_bindingmodel(); + // const auto& bindless = device.get_bindingmodel(); - vkCmdBindPipeline(vk_command_buffer, pipeline.bind_point, pipeline.vk_pipeline); + 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); + // 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); + + VkPushDataInfoEXT push_data { + .sType = VK_STRUCTURE_TYPE_PUSH_DATA_INFO_EXT, + .pNext = nullptr, + .offset = 0, + .data = { + .address = data, + .size = size, + } + }; + vkCmdPushDataEXT(vk_command_buffer, &push_data); - const auto& index_buffer = device.get_buffer(params.index_buffer); - vkCmdBindIndexBuffer(vk_command_buffer, index_buffer.vk_buffer, 0U, VK_INDEX_TYPE_UINT16); + const device_buffer* index_buffer = device.get_buffer(params.index_buffer); + vkCmdBindIndexBuffer(vk_command_buffer, index_buffer->vk_buffer, 0U, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(vk_command_buffer, params.vertex_count, params.instance_count, params.index_offset, static_cast<int32_t>(params.vertex_offset), 0U); } diff --git a/src/vk-device.cpp b/src/vk-device.cpp index 9c1b7a4..988d344 100644 --- a/src/vk-device.cpp +++ b/src/vk-device.cpp @@ -1,8 +1,42 @@ #include "vk-device.hpp" +#include "vk-device-types.hpp" +#include "vulkan-loader.hpp" -#define VMA_IMPLEMENTATION #include <vk_mem_alloc.h> +device_semaphore create_semaphore(VkDevice device, const semaphore_desc& desc, const char* name) { + device_semaphore semaphore { + .value = desc.initial_value, + }; + VkSemaphoreTypeCreateInfo semaphore_type_create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .pNext = nullptr, + .semaphoreType = desc.type, + .initialValue = desc.initial_value, + }; + + VkSemaphoreCreateInfo create_info{ + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &semaphore_type_create_info, + .flags = 0U, + }; + + VKCHECK(vkCreateSemaphore(device, &create_info, nullptr, &semaphore.vk_semaphore)); + + if (name) { + VkDebugUtilsObjectNameInfoEXT object_name{ + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = nullptr, + .objectType = VK_OBJECT_TYPE_SEMAPHORE, + .objectHandle = reinterpret_cast<uint64_t>(semaphore.vk_semaphore), + .pObjectName = name, + }; + vkSetDebugUtilsObjectNameEXT(device, &object_name); + } + return semaphore; +} + + static VkShaderModule create_shader_module(VkDevice device, uint8_t* code, size_t code_size) { VkShaderModule shader_module; VkShaderModuleCreateInfo create_info{ @@ -37,34 +71,46 @@ void vkdevice::init() { create_instance(); + // create debug layer callback #ifdef _DEBUG - create_debug_layer_callback(); + { + VkDebugUtilsMessengerCreateInfoEXT create_info{ + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .pNext = nullptr, + .flags = 0U, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, + .pfnUserCallback = debug_callback, + .pUserData = nullptr, + }; + + VKCHECK(vkCreateDebugUtilsMessengerEXT(instance, &create_info, nullptr, &debug_messenger)); + } #endif // _DEBUG create_device(); - create_memory_allocator(); - - bindless.init(); - - auto semaphore = create_semaphore({ - .type = VK_SEMAPHORE_TYPE_TIMELINE, - }, "timeline_semaphore"); - timeline_semaphore = get_semaphore(semaphore); + fence = create_semaphore( + device, + { + .type = VK_SEMAPHORE_TYPE_TIMELINE, + }, "timeline_semaphore" + ); } void vkdevice::deinit() { vkDeviceWaitIdle(device); - bindless.deinit(); - vmaDestroyAllocator(gpu_allocator); for (auto& queue : queues) { vkDestroyCommandPool(device, queue.command_pool, nullptr); } - vkDestroySemaphore(device, timeline_semaphore.vk_semaphore, nullptr); + vkDestroySemaphore(device, fence.vk_semaphore, nullptr); vkDestroyDevice(device, nullptr); @@ -81,19 +127,20 @@ void vkdevice::wait() { }; void vkdevice::wait_for_fence(u64 value) { - VkSemaphoreWaitInfoKHR semaphore_wait_info { - .type = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR, + VkSemaphoreWaitInfo semaphore_wait_info { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .pNext = nullptr, + .flags = 0U, + .semaphoreCount = 1U, + .pSemaphores = &fence.vk_semaphore, + .pValues = &value, }; - semaphore_wait_info.pSemaphores = &semaphore; - semaphore_wait_info.semaphoreCount = 1; - semaphore_wait_info.pValues = &value; - VK_CHECK(vkWaitSemaphoresKHR(device->get_handle(), &semaphore_wait_info, UINT64_MAX)); + + VKCHECK(vkWaitSemaphores(device, &semaphore_wait_info, UINT64_MAX)); } 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); @@ -113,12 +160,16 @@ handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) { .name = desc.name, }; + VkBufferUsageFlags2CreateInfo usage_flags2 { + .sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR, + .usage = desc.usages, + }; VkBufferCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, + .pNext = &usage_flags2, .flags = 0U, .size = desc.size, - .usage = desc.usages, + .usage = 0U, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, @@ -144,7 +195,7 @@ handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) { 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) { + if ((desc.usages & VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT) != 0U) { VkBufferDeviceAddressInfo address_info { .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, .pNext = nullptr, @@ -263,8 +314,8 @@ handle<device_pipeline> vkdevice::create_graphics_pipeline(const graphics_pipeli .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .pNext = nullptr, .viewMask = 0U, - .colorAttachmentCount = static_cast<uint32_t>(desc.color_attachments_format.size()), - .pColorAttachmentFormats = desc.color_attachments_format.data(), + .colorAttachmentCount = static_cast<uint32_t>(desc.color_attachments_format_count), + .pColorAttachmentFormats = desc.color_attachments_format, .depthAttachmentFormat = VK_FORMAT_UNDEFINED, .stencilAttachmentFormat = VK_FORMAT_UNDEFINED, }; @@ -284,7 +335,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.global_layout, + // .layout = bindless.global_layout, .renderPass = nullptr, .subpass = 0U, .basePipelineHandle = nullptr, @@ -331,7 +382,7 @@ handle<device_pipeline> vkdevice::create_compute_pipeline(const compute_pipeline .pNext = nullptr, .flags = 0U, .stage = stage_create_info, - .layout = bindless.global_layout, + // .layout = bindless.global_layout, .basePipelineHandle = nullptr, .basePipelineIndex = 0, }; @@ -376,172 +427,59 @@ handle<device_surface> vkdevice::create_surface(const surface_desc& desc) { assert(surface_desc::max_image_count >= device_surface.image_count); for (uint32_t index = 0u; index < device_surface.image_count; index++) { - device_surface.acquire_semaphores[index] = create_semaphore({ - .type = VK_SEMAPHORE_TYPE_BINARY, - }, "acquire_semaphore"); - device_surface.submit_semaphores[index] = create_semaphore({ - .type = VK_SEMAPHORE_TYPE_BINARY, - }, "submit_semaphore"); + device_surface.acquire_semaphores[index] = create_semaphore( + device, + { + .type = VK_SEMAPHORE_TYPE_BINARY, + }, "acquire_semaphore" + ); + device_surface.submit_semaphores[index] = create_semaphore( + device, + { + .type = VK_SEMAPHORE_TYPE_BINARY, + }, "submit_semaphore" + ); } return surfaces.add(device_surface); } -handle<device_semaphore> vkdevice::create_semaphore(const semaphore_desc& desc, const char* name) { - device_semaphore semaphore { - .value = desc.initial_value, - }; - VkSemaphoreTypeCreateInfo semaphore_type_create_info{ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - .pNext = nullptr, - .semaphoreType = desc.type, - .initialValue = desc.initial_value, - }; - - VkSemaphoreCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = &semaphore_type_create_info, - .flags = 0U, - }; - - VKCHECK(vkCreateSemaphore(device, &create_info, nullptr, &semaphore.vk_semaphore)); - - if (name) { - VkDebugUtilsObjectNameInfoEXT object_name{ - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, - .pNext = nullptr, - .objectType = VK_OBJECT_TYPE_SEMAPHORE, - .objectHandle = reinterpret_cast<uint64_t>(semaphore.vk_semaphore), - .pObjectName = name, - }; - vkSetDebugUtilsObjectNameEXT(device, &object_name); - } - return semaphores.add(semaphore); -} - void vkdevice::destroy_texture(handle<device_texture> handle) { - auto& texture = get_texture(handle); + device_texture* texture = get_texture(handle); - texture.release(); + texture->release(); textures.remove(handle); } void vkdevice::destroy_buffer(handle<device_buffer> handle) { - const auto& buffer = get_buffer(handle); + device_buffer* buffer = get_buffer(handle); - vmaDestroyBuffer(gpu_allocator, buffer.vk_buffer, buffer.alloc); + vmaDestroyBuffer(gpu_allocator, buffer->vk_buffer, buffer->alloc); buffers.remove(handle); } void vkdevice::destroy_pipeline(handle<device_pipeline> handle) { - const auto& pipeline = vkdevice::get_pipeline(handle); + const device_pipeline* pipeline = get_pipeline(handle); - vkDestroyPipeline(device, pipeline.vk_pipeline, nullptr); + vkDestroyPipeline(device, pipeline->vk_pipeline, nullptr); pipelines.remove(handle); } -void vkdevice::destroy_semaphore(handle<device_semaphore> handle) { - auto& semaphore = vkdevice::get_semaphore(handle); - - vkDestroySemaphore(device, semaphore.vk_semaphore, nullptr); - semaphores.remove(handle); -} - void vkdevice::destroy_surface(handle<device_surface> handle) { - auto& surface = vkdevice::get_surface(handle); + device_surface* surface = get_surface(handle); - for (auto texture_index{0U}; texture_index < surface.image_count; texture_index++) { - auto texture_handle = surface.swapchain_images[texture_index]; - destroy_texture(texture_handle); - } + for (u32 index = 0U; index < surface->image_count; index++) { + destroy_texture(surface->swapchain_images[index]); - for (uint32_t index = 0u; index < surface.image_count; index++) { - destroy_semaphore(surface.acquire_semaphores[index]); - destroy_semaphore(surface.submit_semaphores[index]); + vkDestroySemaphore(device, surface->acquire_semaphores[index].vk_semaphore, nullptr); + vkDestroySemaphore(device, surface->submit_semaphores[index].vk_semaphore, nullptr); } - vkDestroySwapchainKHR(device, surface.vk_swapchain, nullptr); + vkDestroySwapchainKHR(device, surface->vk_swapchain, nullptr); - vkDestroySurfaceKHR(instance, surface.vk_surface, nullptr); + vkDestroySurfaceKHR(instance, surface->vk_surface, nullptr); } -// uint64_t vkdevice::submit(std::span<command_buffer> buffers, handle<device_semaphore> wait_handle, handle<device_semaphore> signal_handle, handle<device_semaphore> fence_handle) { -// assert((max_submitable_command_buffers - buffers.size()) >= 0); -// const auto queue_type = buffers[0].queue_type; -// -// VkCommandBufferSubmitInfo command_buffers_info[buffers.size()]; -// -// for (auto index{ 0U }; index < buffers.size(); index++) { -// assert(queue_type == 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.deviceMask = 0U; -// } -// -// VkSemaphoreSubmitInfo wait_semaphore_info{ -// .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, -// .pNext = nullptr, -// .stageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, -// .deviceIndex = 0U, -// }; -// -// VkSemaphoreSubmitInfo signal_semaphore_infos[2U]; -// -// VkSubmitInfo2 submit_info{ -// .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, -// .pNext = nullptr, -// .flags = 0U, -// .waitSemaphoreInfoCount = 0U, -// .commandBufferInfoCount = static_cast<uint32_t>(buffers.size()), -// .pCommandBufferInfos = command_buffers_info, -// .pSignalSemaphoreInfos = signal_semaphore_infos, -// }; -// -// if (wait_handle.is_valid()) { -// const auto& wait = vkdevice::get_render_device().get_semaphore(wait_handle); -// wait_semaphore_info.semaphore = wait.vk_semaphore; -// wait_semaphore_info.value = wait.value; -// submit_info.waitSemaphoreInfoCount++; -// submit_info.pWaitSemaphoreInfos = &wait_semaphore_info; -// } -// -// if (signal_handle.is_valid()) { -// auto& signal = vkdevice::get_render_device().get_semaphore(signal_handle); -// signal_semaphore_infos[0U] = { -// .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, -// .pNext = nullptr, -// .semaphore = signal.vk_semaphore, -// .value = signal.value, -// .stageMask = VK_PIPELINE_STAGE_2_NONE, -// .deviceIndex = 0U, -// }; -// submit_info.signalSemaphoreInfoCount++; -// } -// -// uint64_t ret = -1; -// -// if (fence_handle.is_valid()) { -// auto& fence = vkdevice::get_render_device().get_semaphore(fence_handle); -// auto fence_index = submit_info.signalSemaphoreInfoCount; -// signal_semaphore_infos[fence_index] = { -// .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, -// .pNext = nullptr, -// .semaphore = fence.vk_semaphore, -// .value = ++fence.value, -// .stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, -// .deviceIndex = 0U, -// }; -// ret = fence.value; -// } -// -// VKCHECK(vkQueueSubmit2(queues[static_cast<uint32_t>(queue_type)].vk_queue, 1, &submit_info, nullptr)); -// -// return ret; -// } - uint64_t vkdevice::submit(command_buffer* cmd_buffers, uint32_t count) { assert((max_submitable_command_buffers - count) >= 0); const auto queue_type = cmd_buffers[0].queue_type; @@ -569,7 +507,6 @@ uint64_t vkdevice::submit(command_buffer* cmd_buffers, uint32_t count) { .pCommandBufferInfos = command_buffers_info, }; - auto& fence = timeline_semaphore; VkSemaphoreSubmitInfo signal_semaphore_infos[] = { { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, @@ -605,8 +542,8 @@ uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle, command_buffer_info.deviceMask = 0U; } - const device_surface& surface = get_surface(surface_handle); - device_semaphore& wait = get_semaphore(surface.acquire_semaphores[surface.frame_index]); + const device_surface* surface = get_surface(surface_handle); + const device_semaphore& wait = surface->acquire_semaphores[surface->frame_index]; VkSemaphoreSubmitInfo wait_semaphore_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, .pNext = nullptr, @@ -626,8 +563,7 @@ uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle, .pCommandBufferInfos = command_buffers_info, }; - auto& fence = timeline_semaphore; - auto& signal = get_semaphore(surface.submit_semaphores[surface.frame_index]); + const device_semaphore& signal = surface->submit_semaphores[surface->frame_index]; VkSemaphoreSubmitInfo signal_semaphore_infos[] = { { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, @@ -655,25 +591,25 @@ uint64_t vkdevice::submit_before_present(handle<device_surface> surface_handle, } void vkdevice::present(handle<device_surface> surface_handle) { - auto& surface = render_device.get_surface(surface_handle); + device_surface* surface = render_device.get_surface(surface_handle); VkResult result; VkPresentInfoKHR present_info{ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, .swapchainCount = 1U, - .pSwapchains = &surface.vk_swapchain, - .pImageIndices = &surface.image_index, + .pSwapchains = &surface->vk_swapchain, + .pImageIndices = &surface->image_index, .pResults = &result, }; - const auto& semaphore = get_semaphore(surface.submit_semaphores[surface.frame_index]); + const device_semaphore& semaphore = surface->submit_semaphores[surface->frame_index]; present_info.waitSemaphoreCount = 1U; present_info.pWaitSemaphores = &semaphore.vk_semaphore; VKCHECK(vkQueuePresentKHR(queues[static_cast<uint32_t>(QueueType::GRAPHICS)].vk_queue, &present_info)); VKCHECK(result); - surface.frame_index = (surface.frame_index + 1) % surface.image_count; + surface->frame_index = (surface->frame_index + 1) % surface->image_count; } // private @@ -738,14 +674,15 @@ void vkdevice::create_swapchain(const surface_desc& desc, device_surface& surfac } { - auto supported = false; - auto supported_formats_count = 0U; + bool supported = false; + u32 supported_formats_count = 0U; VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, vk_surface, &supported_formats_count, nullptr)); - std::vector<VkSurfaceFormatKHR> supported_formats{ supported_formats_count }; - VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, vk_surface, &supported_formats_count, supported_formats.data())); + VkSurfaceFormatKHR* supported_formats = static_cast<VkSurfaceFormatKHR*>(_malloca(supported_formats_count * sizeof(VkSurfaceFormatKHR))); + VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, vk_surface, &supported_formats_count, supported_formats)); - for (auto& surface_format : supported_formats) { + for (u32 format_index = 0U; format_index < supported_formats_count; format_index++) { + VkSurfaceFormatKHR surface_format = supported_formats[format_index]; if (surface_format.format == desc.surface_format.format && surface_format.colorSpace == desc.surface_format.colorSpace) { supported = true; @@ -757,14 +694,15 @@ void vkdevice::create_swapchain(const surface_desc& desc, device_surface& surfac } { - auto supported = false; - auto supported_present_modes_count = 0U; + bool supported = false; + u32 supported_present_modes_count = 0U; VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, vk_surface, &supported_present_modes_count, nullptr)); - std::vector<VkPresentModeKHR> supported_present_modes{ supported_present_modes_count }; - VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, vk_surface, &supported_present_modes_count, supported_present_modes.data())); + VkPresentModeKHR* supported_present_modes = static_cast<VkPresentModeKHR*>(_malloca(supported_present_modes_count * sizeof(VkPresentModeKHR))); + VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, vk_surface, &supported_present_modes_count, supported_present_modes)); - for (auto& present_mode : supported_present_modes) { + for (u32 present_mode_index = 0U; present_mode_index < supported_present_modes_count; present_mode_index++) { + VkPresentModeKHR present_mode = supported_present_modes[present_mode_index]; if (present_mode == desc.present_mode) { supported = true; break; @@ -805,10 +743,10 @@ void vkdevice::create_swapchain(const surface_desc& desc, device_surface& surfac vkGetSwapchainImagesKHR(device, surface.vk_swapchain, &surface.image_count, nullptr); assert(surface.image_count <= surface_desc::max_image_count); - std::vector<VkImage> images {surface.image_count}; - vkGetSwapchainImagesKHR(device, surface.vk_swapchain, &surface.image_count, images.data()); + VkImage* images = static_cast<VkImage*>(_malloca(surface.image_count * sizeof(VkImage))); + vkGetSwapchainImagesKHR(device, surface.vk_swapchain, &surface.image_count, images); - for (auto index {0U}; index < surface.image_count; index++) { + for (u32 index = 0U; index < surface.image_count; index++) { surface.swapchain_images[index] = create_texture({ .width = extent.width, .height = extent.height, @@ -835,14 +773,14 @@ void vkdevice::create_instance() { .apiVersion = VK_API_VERSION_1_3, }; - constexpr const char* instance_layers[]{ + const char* instance_layers[]{ "VK_LAYER_KHRONOS_validation", }; - constexpr const char* instance_extensions[]{ + const char* instance_extensions[]{ VK_EXT_DEBUG_UTILS_EXTENSION_NAME, - "VK_KHR_surface", - "VK_KHR_win32_surface" + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; VkInstanceCreateInfo create_info{ @@ -862,7 +800,34 @@ void vkdevice::create_instance() { } void vkdevice::create_device() { - pick_physical_device(); + // pick physical device + // TODO: change put this in another scope + VkPhysicalDeviceDescriptorHeapPropertiesEXT descriptor_heap_props { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_PROPERTIES_EXT, + }; + { + u32 physical_devices_count = 0U; + vkEnumeratePhysicalDevices(instance, &physical_devices_count, nullptr); + assert(physical_devices_count > 0); + + VkPhysicalDevice* physical_devices = static_cast<VkPhysicalDevice*>(_malloca(physical_devices_count * sizeof(VkPhysicalDevice))); + vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices); + + physical_device_props = VkPhysicalDeviceProperties2 { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &descriptor_heap_props, + }; + + for (u32 physical_device_index = 0U; physical_device_index < physical_devices_count; physical_device_index++) { + VkPhysicalDevice physical_dev = physical_devices[physical_device_index]; + if (device_support_features(physical_dev)) { + physical_device = physical_dev; + break; + } + } + + assert(true); + } float queue_priority = 1.f; VkDeviceQueueCreateInfo queue_create_infos[static_cast<uint32_t>(QueueType::MAX)]; @@ -875,17 +840,17 @@ void vkdevice::create_device() { queue_create_info.pQueuePriorities = &queue_priority; } - auto queue_properties_count = 0U; + u32 queue_properties_count = 0U; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr); - std::vector<VkQueueFamilyProperties> queue_properties{ queue_properties_count }; - vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data()); + VkQueueFamilyProperties* queue_properties = static_cast<VkQueueFamilyProperties*>(_malloca(queue_properties_count * sizeof(VkQueueFamilyProperties))); + vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties); - for (auto index{ 0U }; index < static_cast<uint32_t>(QueueType::MAX); index++) { - auto& queue = queues[index]; + for (u32 index = 0U; index < static_cast<uint32_t>(QueueType::MAX); index++) { + queue& queue = queues[index]; - for (auto properties_index{ 0U }; properties_index < queue_properties_count; properties_index++) { - auto& queue_property = queue_properties[properties_index]; + for (u32 properties_index = 0U; properties_index < queue_properties_count; properties_index++) { + VkQueueFamilyProperties queue_property = queue_properties[properties_index]; if ((queue_property.queueFlags & queue.usages) == queue.usages) { queue_create_infos[index].queueFamilyIndex = queue.index = properties_index; @@ -894,9 +859,10 @@ void vkdevice::create_device() { } } - constexpr const char* device_extensions[] = { + const char* device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - // VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME + VK_EXT_DESCRIPTOR_HEAP_EXTENSION_NAME, + VK_KHR_MAINTENANCE_5_EXTENSION_NAME, }; VkPhysicalDeviceVulkan12Features physical_device_12_features{ @@ -939,78 +905,72 @@ void vkdevice::create_device() { vkGetDeviceQueue(device, queue.index, 0, &queue.vk_queue); } - create_command_pools(); -} - -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, - }; - - VKCHECK(vmaCreateAllocator(&create_info, &gpu_allocator)); -} - -void vkdevice::create_command_pools() { - VkCommandPoolCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - }; + // create command pool + { + VkCommandPoolCreateInfo command_pool_create_info{ + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + }; - for (auto& queue : queues) { - create_info.queueFamilyIndex = queue.index; + for (queue& queue : queues) { + command_pool_create_info.queueFamilyIndex = queue.index; - VKCHECK(vkCreateCommandPool(device, &create_info, nullptr, &queue.command_pool)); + VKCHECK(vkCreateCommandPool(device, &command_pool_create_info, nullptr, &queue.command_pool)); + } } -} -void vkdevice::pick_physical_device() { - auto physical_devices_count = 0U; - vkEnumeratePhysicalDevices(instance, &physical_devices_count, nullptr); - - assert(physical_devices_count > 0); - - std::vector<VkPhysicalDevice> physical_devices{ physical_devices_count }; - vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data()); + // create memory allocator + { + VmaVulkanFunctions functions = { + .vkGetInstanceProcAddr = vkGetInstanceProcAddr, + .vkGetDeviceProcAddr = vkGetDeviceProcAddr, + }; + VmaAllocatorCreateInfo allocator_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, + }; - physical_device_props = VkPhysicalDeviceProperties2 { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - .pNext = nullptr, - }; + VKCHECK(vmaCreateAllocator(&allocator_create_info, &gpu_allocator)); + } - for (auto& physical_dev : physical_devices) { - if (device_support_features(physical_dev)) { - physical_device = physical_dev; + create_heaps(descriptor_heap_props); +} - return; - } +void vkdevice::create_heaps(VkPhysicalDeviceDescriptorHeapPropertiesEXT& descriptor_heap_props) { + // create image heap + { + sampler_heap = create_buffer({ + .size = descriptor_heap_props.minResourceHeapReservedRange + max_images_count * descriptor_heap_props.imageDescriptorSize, + .usages = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT | + VK_BUFFER_USAGE_2_TRANSFER_DST_BIT, + .memory_usage = VMA_MEMORY_USAGE_GPU_ONLY, + .name = "image descriptor_heap", + }); } - assert(true); + // create sampler heap + { + sampler_heap = create_buffer({ + .size = descriptor_heap_props.minSamplerHeapReservedRange + max_samplers_count * descriptor_heap_props.samplerDescriptorSize, + .usages = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT | + VK_BUFFER_USAGE_2_TRANSFER_DST_BIT, + .memory_usage = VMA_MEMORY_USAGE_GPU_ONLY, + .name = "sampler descriptor_heap", + }); + } } + bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { // limits - { - vkGetPhysicalDeviceProperties2(physical_dev, &physical_device_props); - - VkPhysicalDeviceLimits* limits = &physical_device_props.properties.limits; - if (limits->maxPerStageDescriptorSampledImages < 0x10000 || - limits->maxPerStageDescriptorStorageImages < 0x10000 || - limits->maxDescriptorSetSampledImages < 0x10000 || - limits->maxDescriptorSetStorageImages < 0x10000) { - return false; - } - } + vkGetPhysicalDeviceProperties2(physical_dev, &physical_device_props); // Vulkan 1.2 physical device features support { @@ -1025,7 +985,6 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { vkGetPhysicalDeviceFeatures2(physical_dev, &physical_device_features); - // clang-format off if (vulkan_12_features.bufferDeviceAddress == VK_FALSE || vulkan_12_features.runtimeDescriptorArray == VK_FALSE || vulkan_12_features.shaderStorageImageArrayNonUniformIndexing == VK_FALSE || @@ -1035,7 +994,6 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { vulkan_12_features.imagelessFramebuffer == VK_FALSE) { return false; } - // clang-format on } // Vulkan 1.3 physical device features support @@ -1061,25 +1019,6 @@ bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) { return true; } -void vkdevice::create_debug_layer_callback() { -#ifdef _DEBUG - VkDebugUtilsMessengerCreateInfoEXT create_info{ - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .pNext = nullptr, - .flags = 0U, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, - .pfnUserCallback = debug_callback, - .pUserData = nullptr, - }; - - VKCHECK(vkCreateDebugUtilsMessengerEXT(instance, &create_info, nullptr, &debug_messenger)); -#endif // _DEBUG -} - idlist<> device_texture::sampled_indices = {}; idlist<> device_texture::storage_indices = {}; @@ -1087,7 +1026,6 @@ idlist<> device_sampler::sampler_indices = {}; void device_texture::init(const texture_desc& desc) { auto& render_device = vkdevice::get(); - const auto& bindless = render_device.get_bindingmodel(); auto* device = render_device.get_device(); vk_image = desc.vk_image; @@ -1150,59 +1088,91 @@ void device_texture::init(const texture_desc& desc) { vkSetDebugUtilsObjectNameEXT(device, &object_name); } - create_views(); + VkImageViewCreateInfo image_view_create_info{ + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0U, + .image = vk_image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = format, + .components = { + .r = VK_COMPONENT_SWIZZLE_R, + .g = VK_COMPONENT_SWIZZLE_G, + .b = VK_COMPONENT_SWIZZLE_B, + .a = VK_COMPONENT_SWIZZLE_A, + }, + .subresourceRange = { + .aspectMask = aspects, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + // create views + { + for (u32 mip_index = 0U; mip_index < mips; mip_index++) { + image_view_create_info.subresourceRange.baseMipLevel = mip_index; + VKCHECK(vkCreateImageView(device, &image_view_create_info, nullptr, &mips_views[mip_index])); + } + + image_view_create_info.subresourceRange.baseMipLevel = 0; + image_view_create_info.subresourceRange.levelCount = mips; + VKCHECK(vkCreateImageView(device, &image_view_create_info, nullptr, &whole_view)); + } // TODO: Handle mips views - VkDescriptorImageInfo images_info[]{ - { - nullptr, - whole_view, - VK_IMAGE_LAYOUT_GENERAL, - }, + VkImageDescriptorInfoEXT image_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT, + .pNext = nullptr, + .pView = &image_view_create_info, + .layout = VK_IMAGE_LAYOUT_GENERAL, }; - std::vector<VkWriteDescriptorSet> write_descriptor_sets; + u32 descriptors_count = 0U; + VkResourceDescriptorInfoEXT resource_descriptor_infos[2U]; + VkHostAddressRangeEXT resources_address[2U]; if ((desc.usages & VK_IMAGE_USAGE_STORAGE_BIT) != 0) { - storage_index = storage_indices.add(); + resource_descriptor_infos[descriptors_count] = VkResourceDescriptorInfoEXT{ + .sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT, + .pNext = nullptr, + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .data = { + .pImage = &image_info, + }, + }; - write_descriptor_sets.push_back({ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - // .dstSet = bindless.sets[BindlessSetType::GLOBAL], - .dstSet = bindless.global_set, - .dstBinding = 2U, - .dstArrayElement = storage_index.id, - .descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo), - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .pImageInfo = images_info, - .pBufferInfo = nullptr, - .pTexelBufferView = nullptr, - }); + // resource_address[descriptors_count] = { + // .address = storage_indices.add(), + // .size = , + // } + + descriptors_count++; } if ((desc.usages & VK_IMAGE_USAGE_SAMPLED_BIT) != 0) { - sampled_index = sampled_indices.add(); + resource_descriptor_infos[descriptors_count] = VkResourceDescriptorInfoEXT{ + .sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT, + .pNext = nullptr, + .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .data = { + .pImage = &image_info, + }, + }; - write_descriptor_sets.push_back({ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - // .dstSet = bindless.sets[BindlessSetType::GLOBAL], - .dstSet = bindless.global_set, - .dstBinding = 1U, - .dstArrayElement = sampled_index.id, - .descriptorCount = sizeof(images_info) / sizeof(VkDescriptorImageInfo), - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - .pImageInfo = images_info, - .pBufferInfo = nullptr, - .pTexelBufferView = nullptr, - }); + // resource_address[descriptors_count] = { + // .address = sampled_indices.add(), + // .size = , + // } + + descriptors_count++; } - vkUpdateDescriptorSets(device, static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0U, nullptr); + VKCHECK(vkWriteResourceDescriptorsEXT(device, static_cast<uint32_t>(descriptors_count), resource_descriptor_infos, resources_address)); } void device_texture::release() { - auto& render_device = vkdevice::get(); - auto* device = render_device.get_device(); + vkdevice& render_device = vkdevice::get(); + VkDevice device = render_device.get_device(); auto* gpu_allocator = render_device.get_allocator(); if (alloc != nullptr) { @@ -1226,44 +1196,11 @@ void device_texture::release() { } void device_texture::create_views() { - auto* device = vkdevice::get().get_device(); - - VkImageViewCreateInfo create_info{ - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0U, - .image = vk_image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = format, - .components = { - .r = VK_COMPONENT_SWIZZLE_R, - .g = VK_COMPONENT_SWIZZLE_G, - .b = VK_COMPONENT_SWIZZLE_B, - .a = VK_COMPONENT_SWIZZLE_A, - }, - .subresourceRange = { - .aspectMask = aspects, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - - for (auto mip_index{ 0U }; mip_index < mips; mip_index++) { - create_info.subresourceRange.baseMipLevel = mip_index; - VKCHECK(vkCreateImageView(device, &create_info, nullptr, &mips_views[mip_index])); - } - - create_info.subresourceRange.baseMipLevel = 0; - create_info.subresourceRange.levelCount = mips; - VKCHECK(vkCreateImageView(device, &create_info, nullptr, &whole_view)); } void device_sampler::init(const sampler_desc& desc) { auto& render_device = vkdevice::get(); - // const auto& bindless = render_device.get_bindingmodel(); auto* device = render_device.get_device(); VkSamplerCreateInfo sampler_create_info{ @@ -1303,23 +1240,27 @@ void device_sampler::init(const sampler_desc& desc) { // .pBufferInfo = nullptr, // .pTexelBufferView = nullptr, // }); + + // TODO: Write samplers to heap + // TODO: Create previously immutable samplers + VKCHECK(vkWriteSamplerDescriptorsEXT()); } uint32_t vkdevice::acquire_image_index(handle<device_surface> surface_handle) { - auto& surface = get_surface(surface_handle); - const auto& signal = get_semaphore(surface.acquire_semaphores[surface.frame_index]); + device_surface* surface = get_surface(surface_handle); + const device_semaphore& signal = surface->acquire_semaphores[surface->frame_index]; VkSemaphoreWaitInfo wait_info { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, .pNext = nullptr, .flags = 0U, .semaphoreCount = 1U, - .pSemaphores = &timeline_semaphore.vk_semaphore, - .pValues = &timeline_semaphore.value, + .pSemaphores = &fence.vk_semaphore, + .pValues = &fence.value, }; vkWaitSemaphores(device, &wait_info, UINT64_MAX); - VKCHECK(vkAcquireNextImageKHR(device, surface.vk_swapchain, UINT64_MAX, signal.vk_semaphore, nullptr, &surface.image_index)); + VKCHECK(vkAcquireNextImageKHR(device, surface->vk_swapchain, UINT64_MAX, signal.vk_semaphore, nullptr, &surface->image_index)); - return surface.image_index; + return surface->image_index; } |
