diff options
Diffstat (limited to 'deimos')
-rw-r--r-- | deimos/core/allocator.h | 13 | ||||
-rw-r--r-- | deimos/vulkan/vulkan_backend.cpp | 149 | ||||
-rw-r--r-- | deimos/vulkan/vulkan_device_functions.inc | 5 |
3 files changed, 158 insertions, 9 deletions
diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h index f6adea2..569b0df 100644 --- a/deimos/core/allocator.h +++ b/deimos/core/allocator.h @@ -188,6 +188,19 @@ public: }
return Span<T>{ (T*)raw, count };
}
+
+ template<typename T>
+ void DeleteArray(gsl::owner<Span<T>> arr, const SourceLocation& source_location = {})
+ {
+ if constexpr (!std::is_trivially_destructible_v<T>)
+ {
+ for (T* p = arr.data(), end = arr.end(); p < end; ++p)
+ {
+ p->~T();
+ }
+ }
+ Free(arr.data(), arr.size_bytes(), source_location);
+ }
};
class AllocatorApi
diff --git a/deimos/vulkan/vulkan_backend.cpp b/deimos/vulkan/vulkan_backend.cpp index cc54d4d..4334111 100644 --- a/deimos/vulkan/vulkan_backend.cpp +++ b/deimos/vulkan/vulkan_backend.cpp @@ -9,10 +9,66 @@ #include <deimos/core/os.h>
#include <deimos/render/backend.h>
-namespace
+using namespace deimos;
+
+void DeimosFormat(IWriter* writer, VkResult res)
{
+#define PRINT_RESULT(X) case VK_##X: writer->Write(AsBytes(StringView(#X))); break;
+ switch (res)
+ {
+ PRINT_RESULT(SUCCESS);
+ PRINT_RESULT(NOT_READY);
+ PRINT_RESULT(TIMEOUT);
+ PRINT_RESULT(EVENT_SET);
+ PRINT_RESULT(EVENT_RESET);
+ PRINT_RESULT(INCOMPLETE);
+ PRINT_RESULT(ERROR_OUT_OF_HOST_MEMORY);
+ PRINT_RESULT(ERROR_OUT_OF_DEVICE_MEMORY);
+ PRINT_RESULT(ERROR_INITIALIZATION_FAILED);
+ PRINT_RESULT(ERROR_DEVICE_LOST);
+ PRINT_RESULT(ERROR_MEMORY_MAP_FAILED);
+ PRINT_RESULT(ERROR_LAYER_NOT_PRESENT);
+ PRINT_RESULT(ERROR_EXTENSION_NOT_PRESENT);
+ PRINT_RESULT(ERROR_FEATURE_NOT_PRESENT);
+ PRINT_RESULT(ERROR_INCOMPATIBLE_DRIVER);
+ PRINT_RESULT(ERROR_TOO_MANY_OBJECTS);
+ PRINT_RESULT(ERROR_FORMAT_NOT_SUPPORTED);
+ PRINT_RESULT(ERROR_FRAGMENTED_POOL);
+ PRINT_RESULT(ERROR_UNKNOWN);
+ PRINT_RESULT(ERROR_OUT_OF_POOL_MEMORY);
+ PRINT_RESULT(ERROR_INVALID_EXTERNAL_HANDLE);
+ PRINT_RESULT(ERROR_FRAGMENTATION);
+ PRINT_RESULT(ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
+ PRINT_RESULT(PIPELINE_COMPILE_REQUIRED);
+ PRINT_RESULT(ERROR_SURFACE_LOST_KHR);
+ PRINT_RESULT(ERROR_NATIVE_WINDOW_IN_USE_KHR);
+ PRINT_RESULT(SUBOPTIMAL_KHR);
+ PRINT_RESULT(ERROR_OUT_OF_DATE_KHR);
+ PRINT_RESULT(ERROR_INCOMPATIBLE_DISPLAY_KHR);
+ PRINT_RESULT(ERROR_VALIDATION_FAILED_EXT);
+ PRINT_RESULT(ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_NOT_PERMITTED_KHR);
+ PRINT_RESULT(ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
+ PRINT_RESULT(THREAD_IDLE_KHR);
+ PRINT_RESULT(THREAD_DONE_KHR);
+ PRINT_RESULT(OPERATION_DEFERRED_KHR);
+ PRINT_RESULT(OPERATION_NOT_DEFERRED_KHR);
+ PRINT_RESULT(ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
+ PRINT_RESULT(ERROR_INVALID_SHADER_NV);
+ PRINT_RESULT(ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
+ PRINT_RESULT(ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
+ PRINT_RESULT(ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR);
+ PRINT_RESULT(ERROR_COMPRESSION_EXHAUSTED_EXT);
+ PRINT_RESULT(RESULT_MAX_ENUM);
+ }
+}
-using namespace deimos;
+namespace
+{
LogApi* log_api;
OsApi* os_api;
@@ -24,7 +80,9 @@ const VkAllocationCallbacks* kVkAlloc = nullptr; struct VulkanSwapchain: public RenderSwapchain
{
- VkSwapchainKHR swapchain{};
+ VkSwapchainKHR swapchain{};
+ VkFormat format{};
+ gsl::owner<Span<VkImage>> images;
};
class VulkanBackendImpl : public IVulkanBackend, public IRenderBackend
@@ -40,7 +98,8 @@ class VulkanBackendImpl : public IVulkanBackend, public IRenderBackend struct FrameResources
{
- VkCommandPool cmd_pool = VK_NULL_HANDLE;
+ VkCommandPool cmd_pool = VK_NULL_HANDLE;
+ VkCommandBuffer cmd_buffer = VK_NULL_HANDLE;
};
FrameResources m_frame_resources;
@@ -78,13 +137,65 @@ public: VkResult res = m_vk->CreateCommandPool(m_device, &create_info, kVkAlloc, &m_frame_resources.cmd_pool);
if (res != VK_SUCCESS)
{
- log_api->LogError("Couldn't allocate Vulkan command pool: $", (int)res);
+ log_api->LogError("Couldn't allocate Vulkan command pool: $", res);
return;
}
+
+ VkCommandBufferAllocateInfo alloc_info{};
+ alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ alloc_info.pNext = nullptr;
+ alloc_info.commandPool = m_frame_resources.cmd_pool;
+ alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ alloc_info.commandBufferCount = 1;
+
+ res = m_vk->AllocateCommandBuffers(m_device, &alloc_info, &m_frame_resources.cmd_buffer);
+ if (res != VK_SUCCESS)
+ {
+ log_api->LogError("Couldn't allocate Vulkan command buffer: $", res);
+ }
+
+ VkCommandBufferBeginInfo begin_info{};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.pNext = nullptr;
+ begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ begin_info.pInheritanceInfo = nullptr;
+
+ res = m_vk->BeginCommandBuffer(m_frame_resources.cmd_buffer, &begin_info);
+ if (res != VK_SUCCESS)
+ {
+ log_api->LogError("Couldn't begin Vulkan command buffer recording: $", res);
+ }
}
void EndFrame() override
{
+ VkResult res = m_vk->EndCommandBuffer(m_frame_resources.cmd_buffer);
+ if (res != VK_SUCCESS)
+ {
+ log_api->LogError("Couldn't end Vulkan command buffer recording: $", res);
+ }
+
+ VkCommandBufferSubmitInfo cmd_buffer_submit_info{};
+ cmd_buffer_submit_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO;
+ cmd_buffer_submit_info.pNext = nullptr;
+ cmd_buffer_submit_info.commandBuffer = m_frame_resources.cmd_buffer;
+ cmd_buffer_submit_info.deviceMask = 0;
+
+ VkSubmitInfo2 submit_info{};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2;
+ submit_info.pNext = nullptr;
+ submit_info.flags = 0;
+ submit_info.waitSemaphoreInfoCount = 0;
+ submit_info.commandBufferInfoCount = 1;
+ submit_info.pCommandBufferInfos = &cmd_buffer_submit_info;
+ submit_info.signalSemaphoreInfoCount = 0;
+
+ res = m_vk->QueueSubmit2(m_queue, 1, &submit_info, VK_NULL_HANDLE);
+ if (res != VK_SUCCESS)
+ {
+ log_api->LogError("Couldn't submit Vulkan queue: $", res);
+ }
+
m_vk->DeviceWaitIdle(m_device);
m_vk->DestroyCommandPool(m_device, m_frame_resources.cmd_pool, kVkAlloc);
}
@@ -148,7 +259,7 @@ public: return RuntimeError("No acceptable Vulkan swapchain format found");
}
- VkSwapchainCreateInfoKHR create_info = {
+ const VkSwapchainCreateInfoKHR create_info = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
@@ -177,15 +288,29 @@ public: }
auto* swapchain = m_allocator->New<VulkanSwapchain>();
- swapchain->swapchain = vk_swapchain;
+ swapchain->swapchain = vk_swapchain;
+ swapchain->format = format.format;
+
+ uint32_t image_count = 0;
+ res = m_vk->GetSwapchainImagesKHR(m_device, vk_swapchain, &image_count, nullptr);
+ if (res != VK_SUCCESS)
+ {
+ return RuntimeError("Error when retrieving Vulkan swapchain images");
+ }
+
+ swapchain->images = m_allocator->NewArray<VkImage>(image_count);
+ m_vk->GetSwapchainImagesKHR(m_device, vk_swapchain, &image_count, swapchain->images.data());
+
+ log_api->LogInfo("Vulkan swapchain created with $ images, format $, present mode $", image_count, (int)format.format, (int)present_mode);
return swapchain;
}
void DestroySwapchain(gsl::owner<RenderSwapchain*> swapchain) override
{
- auto* vk_swapchain = (VulkanSwapchain*)swapchain;
+ auto* vk_swapchain = (VulkanSwapchain*)swapchain; // NOLINT
m_vk->DestroySwapchainKHR(m_device, vk_swapchain->swapchain, kVkAlloc);
+ m_allocator->DeleteArray(vk_swapchain->images);
m_allocator->Delete(swapchain);
}
};
@@ -358,10 +483,16 @@ StatusOr<VkDevice> CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, const char* extensions[]{
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
+
+ const VkPhysicalDeviceSynchronization2Features synchronization2_features{
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES,
+ .pNext = nullptr,
+ .synchronization2 = VK_TRUE,
+ };
const VkDeviceCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
- .pNext = nullptr,
+ .pNext = &synchronization2_features,
.flags = 0,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queue_create_info,
diff --git a/deimos/vulkan/vulkan_device_functions.inc b/deimos/vulkan/vulkan_device_functions.inc index f6e6a30..6aa30d2 100644 --- a/deimos/vulkan/vulkan_device_functions.inc +++ b/deimos/vulkan/vulkan_device_functions.inc @@ -6,6 +6,11 @@ FN(GetDeviceQueue) FN(CreateCommandPool)
FN(ResetCommandPool)
FN(DestroyCommandPool)
+FN(AllocateCommandBuffers)
+FN(FreeCommandBuffers)
+FN(BeginCommandBuffer)
+FN(EndCommandBuffer)
+FN(QueueSubmit2)
FN(CreateSwapchainKHR)
FN(DestroySwapchainKHR)
|