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 /src/vk-device.cpp | |
| parent | 92e09dc06f8c8dd5b7a9323d586f4bf642078727 (diff) | |
Inital work on vulkan descriptor heap implementation
Diffstat (limited to 'src/vk-device.cpp')
| -rw-r--r-- | src/vk-device.cpp | 665 |
1 files changed, 303 insertions, 362 deletions
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; } |
