From 4e6897aa8c8769a556ad58081eba5a90226e551d Mon Sep 17 00:00:00 2001 From: omnisci3nce Date: Sat, 27 Apr 2024 15:37:52 +1000 Subject: wip --- src/systems/terrain.h | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/systems/terrain.h (limited to 'src/systems/terrain.h') diff --git a/src/systems/terrain.h b/src/systems/terrain.h new file mode 100644 index 0000000..fa2d3b3 --- /dev/null +++ b/src/systems/terrain.h @@ -0,0 +1,10 @@ +/** + * @file terrain.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ -- cgit v1.2.3-70-g09d2 From c72440f89cfabe0c7752f9105cfc244a79016965 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 27 Apr 2024 15:58:03 +1000 Subject: expanding desired containers --- src/core.h | 8 +- src/renderer/backends/backend_vulkan.c | 1813 ++++++++++++++++---------------- src/std/containers/graphs.h | 15 + src/std/containers/hashset.h | 10 + src/std/containers/hashtable.h | 10 + src/systems/terrain.h | 9 + 6 files changed, 960 insertions(+), 905 deletions(-) create mode 100644 src/std/containers/graphs.h create mode 100644 src/std/containers/hashset.h create mode 100644 src/std/containers/hashtable.h (limited to 'src/systems/terrain.h') diff --git a/src/core.h b/src/core.h index 68bf957..dd5a695 100644 --- a/src/core.h +++ b/src/core.h @@ -3,18 +3,22 @@ #include "defines.h" #include "input.h" #include "ral.h" -// #include "render_types.h" +#include "terrain.h" #include "screenspace.h" #include "text.h" #include "threadpool.h" typedef struct core { - // TODO: Add application name + const char* app_name; + // foundations renderer renderer; threadpool threadpool; + // systems input_state input; text_system_state text; + terrain_state terrain; screenspace_state screenspace; + // data storage model_darray* models; } core; diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 4d3a14e..75b0439 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -923,1061 +923,1068 @@ void vulkan_image_transition_layout(vulkan_context* context, vulkan_command_buff vulkan_image* image, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout) { VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; -void vulkan_image_transition_layout(vulkan_context* context, vulkan_command_buffer* command_buffer, - vulkan_image* image, VkFormat format, VkImageLayout old_layout, - VkImageLayout new_layout) { - VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - barrier.oldLayout = old_layout; - barrier.newLayout = new_layout; - barrier.srcQueueFamilyIndex = context->device.graphics_queue_index; - barrier.dstQueueFamilyIndex = context->device.graphics_queue_index; - barrier.image = image->handle; - barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = 0; - - VkPipelineStageFlags source_stage; - VkPipelineStageFlags dest_stage; - - if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && - new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + void vulkan_image_transition_layout( + vulkan_context * context, vulkan_command_buffer * command_buffer, vulkan_image * image, + VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout) { + VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = context->device.graphics_queue_index; + barrier.dstQueueFamilyIndex = context->device.graphics_queue_index; + barrier.image = image->handle; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; barrier.srcAccessMask = 0; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dest_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - - } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && - new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } else { - FATAL("Unsupported image layout transition"); - return; - } + barrier.dstAccessMask = 0; - vkCmdPipelineBarrier(command_buffer->handle, source_stage, dest_stage, 0, 0, 0, 0, 0, 1, - &barrier); -} + VkPipelineStageFlags source_stage; + VkPipelineStageFlags dest_stage; -void vulkan_image_copy_from_buffer(vulkan_image* image, VkBuffer buffer, - vulkan_command_buffer* command_buffer) { - VkBufferImageCopy region; - region.bufferOffset = 0; - region.bufferRowLength = 0; - region.bufferImageHeight = 0; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.mipLevel = 0; - region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = 1; - printf("Image details width: %d height %d\n", image->width, image->height); - region.imageOffset.x = 0; - region.imageOffset.y = 0; - region.imageOffset.z = 0; - region.imageExtent.width = image->width; - region.imageExtent.height = image->height; - region.imageExtent.depth = 1; - - vkCmdCopyBufferToImage(command_buffer->handle, buffer, image->handle, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); -} + if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && + new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; -void vulkan_image_create(vulkan_context* context, VkImageType image_type, u32 width, u32 height, - VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, - VkMemoryPropertyFlags memory_flags, bool create_view, - VkImageAspectFlags aspect_flags, vulkan_image* out_image) { - // copy params - out_image->width = width; - out_image->height = height; - - // create info - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; - image_create_info.imageType = image_type; - image_create_info.extent.width = width; - image_create_info.extent.height = height; - image_create_info.extent.depth = 1; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = 1; - image_create_info.format = format; - image_create_info.tiling = tiling; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - image_create_info.usage = usage; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VK_CHECK(vkCreateImage(context->device.logical_device, &image_create_info, context->allocator, - &out_image->handle)); - - VkMemoryRequirements memory_reqs; - vkGetImageMemoryRequirements(context->device.logical_device, out_image->handle, &memory_reqs); - - i32 memory_type = -1; - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties(context->device.physical_device, &memory_properties); + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dest_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - for (u32 i = 0; i < memory_properties.memoryTypeCount; i++) { - // typefilter = memoryTypeBits , prop filter = memory_flags - if (memory_reqs.memoryTypeBits & (1 << i) && - (memory_properties.memoryTypes[i].propertyFlags & memory_flags)) { - memory_type = i; - break; + } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && + new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else { + FATAL("Unsupported image layout transition"); + return; } + + vkCmdPipelineBarrier(command_buffer->handle, source_stage, dest_stage, 0, 0, 0, 0, 0, 1, + &barrier); } - if (memory_type < 0) { - ERROR_EXIT("couldnt find a suitable memory type for the image"); + void vulkan_image_copy_from_buffer(vulkan_image * image, VkBuffer buffer, + vulkan_command_buffer * command_buffer) { + VkBufferImageCopy region; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + printf("Image details width: %d height %d\n", image->width, image->height); + region.imageOffset.x = 0; + region.imageOffset.y = 0; + region.imageOffset.z = 0; + region.imageExtent.width = image->width; + region.imageExtent.height = image->height; + region.imageExtent.depth = 1; + + vkCmdCopyBufferToImage(command_buffer->handle, buffer, image->handle, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); } - // allocate memory - VkMemoryAllocateInfo memory_allocate_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - memory_allocate_info.allocationSize = memory_reqs.size; - memory_allocate_info.memoryTypeIndex = memory_type; - vkAllocateMemory(context->device.logical_device, &memory_allocate_info, context->allocator, - &out_image->memory); + void vulkan_image_create(vulkan_context * context, VkImageType image_type, u32 width, u32 height, + VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, + VkMemoryPropertyFlags memory_flags, bool create_view, + VkImageAspectFlags aspect_flags, vulkan_image* out_image) { + // copy params + out_image->width = width; + out_image->height = height; + + // create info + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = image_type; + image_create_info.extent.width = width; + image_create_info.extent.height = height; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.format = format; + image_create_info.tiling = tiling; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_create_info.usage = usage; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VK_CHECK(vkCreateImage(context->device.logical_device, &image_create_info, context->allocator, + &out_image->handle)); + + VkMemoryRequirements memory_reqs; + vkGetImageMemoryRequirements(context->device.logical_device, out_image->handle, &memory_reqs); + + i32 memory_type = -1; + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties(context->device.physical_device, &memory_properties); + + for (u32 i = 0; i < memory_properties.memoryTypeCount; i++) { + // typefilter = memoryTypeBits , prop filter = memory_flags + if (memory_reqs.memoryTypeBits & (1 << i) && + (memory_properties.memoryTypes[i].propertyFlags & memory_flags)) { + memory_type = i; + break; + } + } - // bind memory - // TODO: maybe bind context->device.logical_device to device at the top of the functions? - vkBindImageMemory(context->device.logical_device, out_image->handle, out_image->memory, 0); + if (memory_type < 0) { + ERROR_EXIT("couldnt find a suitable memory type for the image"); + } - if (create_view) { - out_image->view = 0; - vulkan_image_view_create(context, format, out_image, aspect_flags); - } -} + // allocate memory + VkMemoryAllocateInfo memory_allocate_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + memory_allocate_info.allocationSize = memory_reqs.size; + memory_allocate_info.memoryTypeIndex = memory_type; + vkAllocateMemory(context->device.logical_device, &memory_allocate_info, context->allocator, + &out_image->memory); -// TODO: vulkan_image_destroy + // bind memory + // TODO: maybe bind context->device.logical_device to device at the top of the functions? + vkBindImageMemory(context->device.logical_device, out_image->handle, out_image->memory, 0); -void vulkan_framebuffer_create(vulkan_context* context, vulkan_renderpass* renderpass, u32 width, - u32 height, u32 attachment_count, VkImageView* attachments, - vulkan_framebuffer* out_framebuffer) { - out_framebuffer->attachments = malloc(sizeof(VkImageView) * attachment_count); - for (u32 i = 0; i < attachment_count; i++) { - out_framebuffer->attachments[i] = attachments[i]; + if (create_view) { + out_image->view = 0; + vulkan_image_view_create(context, format, out_image, aspect_flags); + } } - out_framebuffer->attachment_count = attachment_count; - out_framebuffer->renderpass = renderpass; - - VkFramebufferCreateInfo framebuffer_create_info = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO - }; // TODO - - framebuffer_create_info.renderPass = renderpass->handle; - framebuffer_create_info.attachmentCount = attachment_count; - framebuffer_create_info.pAttachments = out_framebuffer->attachments; - framebuffer_create_info.width = width; - framebuffer_create_info.height = height; - framebuffer_create_info.layers = 1; - - vkCreateFramebuffer(context->device.logical_device, &framebuffer_create_info, context->allocator, - &out_framebuffer->handle); -} -// TODO: vulkan_framebuffer_destroy - -void vulkan_command_buffer_allocate(vulkan_context* context, VkCommandPool pool, bool is_primary, - vulkan_command_buffer* out_command_buffer) { - VkCommandBufferAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; - allocate_info.commandPool = pool; - allocate_info.level = - is_primary ? VK_COMMAND_BUFFER_LEVEL_PRIMARY : VK_COMMAND_BUFFER_LEVEL_SECONDARY; - allocate_info.commandBufferCount = 1; - allocate_info.pNext = 0; - - out_command_buffer->state = COMMAND_BUFFER_STATE_NOT_ALLOCATED; - vkAllocateCommandBuffers(context->device.logical_device, &allocate_info, - &out_command_buffer->handle); - out_command_buffer->state = COMMAND_BUFFER_STATE_READY; -} + // TODO: vulkan_image_destroy -void vulkan_command_buffer_free(vulkan_context* context, VkCommandPool pool, - vulkan_command_buffer* out_command_buffer) { - // TODO: implement freeing -} + void vulkan_framebuffer_create(vulkan_context * context, vulkan_renderpass * renderpass, + u32 width, u32 height, u32 attachment_count, + VkImageView * attachments, vulkan_framebuffer * out_framebuffer) { + out_framebuffer->attachments = malloc(sizeof(VkImageView) * attachment_count); + for (u32 i = 0; i < attachment_count; i++) { + out_framebuffer->attachments[i] = attachments[i]; + } + out_framebuffer->attachment_count = attachment_count; + out_framebuffer->renderpass = renderpass; + + VkFramebufferCreateInfo framebuffer_create_info = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO + }; // TODO + + framebuffer_create_info.renderPass = renderpass->handle; + framebuffer_create_info.attachmentCount = attachment_count; + framebuffer_create_info.pAttachments = out_framebuffer->attachments; + framebuffer_create_info.width = width; + framebuffer_create_info.height = height; + framebuffer_create_info.layers = 1; + + vkCreateFramebuffer(context->device.logical_device, &framebuffer_create_info, + context->allocator, &out_framebuffer->handle); + } -void vulkan_command_buffer_begin(vulkan_command_buffer* command_buffer, bool is_single_use, - bool is_renderpass_continue, bool is_simultaneous_use) { - VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - begin_info.flags = 0; - if (is_single_use) { - begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + // TODO: vulkan_framebuffer_destroy + + void vulkan_command_buffer_allocate(vulkan_context * context, VkCommandPool pool, bool is_primary, + vulkan_command_buffer* out_command_buffer) { + VkCommandBufferAllocateInfo allocate_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + allocate_info.commandPool = pool; + allocate_info.level = + is_primary ? VK_COMMAND_BUFFER_LEVEL_PRIMARY : VK_COMMAND_BUFFER_LEVEL_SECONDARY; + allocate_info.commandBufferCount = 1; + allocate_info.pNext = 0; + + out_command_buffer->state = COMMAND_BUFFER_STATE_NOT_ALLOCATED; + vkAllocateCommandBuffers(context->device.logical_device, &allocate_info, + &out_command_buffer->handle); + out_command_buffer->state = COMMAND_BUFFER_STATE_READY; } - // TODO: RENDER_PASS_CONTINUE_BIT & SIMULTANEOUS_USE_BIT - begin_info.pNext = 0; - begin_info.pInheritanceInfo = 0; - vkBeginCommandBuffer(command_buffer->handle, &begin_info); + void vulkan_command_buffer_free(vulkan_context * context, VkCommandPool pool, + vulkan_command_buffer * out_command_buffer) { + // TODO: implement freeing + } - command_buffer->state = COMMAND_BUFFER_STATE_RECORDING; -} + void vulkan_command_buffer_begin(vulkan_command_buffer * command_buffer, bool is_single_use, + bool is_renderpass_continue, bool is_simultaneous_use) { + VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + begin_info.flags = 0; + if (is_single_use) { + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + } + // TODO: RENDER_PASS_CONTINUE_BIT & SIMULTANEOUS_USE_BIT -void vulkan_command_buffer_end(vulkan_command_buffer* command_buffer) { - VK_CHECK(vkEndCommandBuffer(command_buffer->handle)); - command_buffer->state = COMMAND_BUFFER_STATE_RECORDING_ENDED; -} -void vulkan_command_buffer_update_submitted(vulkan_command_buffer* command_buffer) { - command_buffer->state = COMMAND_BUFFER_STATE_SUBMITTED; -} -void vulkan_command_buffer_reset(vulkan_command_buffer* command_buffer) { - command_buffer->state = COMMAND_BUFFER_STATE_READY; -} + begin_info.pNext = 0; + begin_info.pInheritanceInfo = 0; + vkBeginCommandBuffer(command_buffer->handle, &begin_info); -void vulkan_command_buffer_allocate_and_begin_oneshot(vulkan_context* context, VkCommandPool pool, - vulkan_command_buffer* out_command_buffer) { - vulkan_command_buffer_allocate(context, pool, true, out_command_buffer); - vulkan_command_buffer_begin(out_command_buffer, true, false, false); -} + command_buffer->state = COMMAND_BUFFER_STATE_RECORDING; + } -void vulkan_command_buffer_end_oneshot(vulkan_context* context, VkCommandPool pool, - vulkan_command_buffer* command_buffer, VkQueue queue) { - vulkan_command_buffer_end(command_buffer); + void vulkan_command_buffer_end(vulkan_command_buffer * command_buffer) { + VK_CHECK(vkEndCommandBuffer(command_buffer->handle)); + command_buffer->state = COMMAND_BUFFER_STATE_RECORDING_ENDED; + } + void vulkan_command_buffer_update_submitted(vulkan_command_buffer * command_buffer) { + command_buffer->state = COMMAND_BUFFER_STATE_SUBMITTED; + } + void vulkan_command_buffer_reset(vulkan_command_buffer * command_buffer) { + command_buffer->state = COMMAND_BUFFER_STATE_READY; + } - // submit to queue - VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer->handle; - VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, 0)); - // wait for it to finish - VK_CHECK(vkQueueWaitIdle(queue)); + void vulkan_command_buffer_allocate_and_begin_oneshot( + vulkan_context * context, VkCommandPool pool, vulkan_command_buffer * out_command_buffer) { + vulkan_command_buffer_allocate(context, pool, true, out_command_buffer); + vulkan_command_buffer_begin(out_command_buffer, true, false, false); + } - vulkan_command_buffer_free(context, pool, command_buffer); -} + void vulkan_command_buffer_end_oneshot(vulkan_context * context, VkCommandPool pool, + vulkan_command_buffer * command_buffer, VkQueue queue) { + vulkan_command_buffer_end(command_buffer); -void vulkan_buffer_copy_to(vulkan_context* context, VkCommandPool pool, VkFence fence, - VkQueue queue, VkBuffer source, u64 source_offset, VkBuffer dest, - u64 dest_offset, u64 size) { - vkQueueWaitIdle(queue); + // submit to queue + VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer->handle; + VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, 0)); + // wait for it to finish + VK_CHECK(vkQueueWaitIdle(queue)); - vulkan_command_buffer temp_cmd_buf; - vulkan_command_buffer_allocate_and_begin_oneshot(context, pool, &temp_cmd_buf); + vulkan_command_buffer_free(context, pool, command_buffer); + } - VkBufferCopy copy_region; - copy_region.srcOffset = source_offset; - copy_region.dstOffset = dest_offset; - copy_region.size = size; + void vulkan_buffer_copy_to(vulkan_context * context, VkCommandPool pool, VkFence fence, + VkQueue queue, VkBuffer source, u64 source_offset, VkBuffer dest, + u64 dest_offset, u64 size) { + vkQueueWaitIdle(queue); - vkCmdCopyBuffer(temp_cmd_buf.handle, source, dest, 1, ©_region); + vulkan_command_buffer temp_cmd_buf; + vulkan_command_buffer_allocate_and_begin_oneshot(context, pool, &temp_cmd_buf); - vulkan_command_buffer_end_oneshot(context, pool, &temp_cmd_buf, queue); -} + VkBufferCopy copy_region; + copy_region.srcOffset = source_offset; + copy_region.dstOffset = dest_offset; + copy_region.size = size; -void vulkan_swapchain_create(vulkan_context* context, u32 width, u32 height, - vulkan_swapchain* out_swapchain) { - VkExtent2D swapchain_extent = { width, height }; - out_swapchain->max_frames_in_flight = 2; // support triple buffering - - // find a format - bool found; - for (u32 i = 0; i < context->device.swapchain_support.format_count; i++) { - VkSurfaceFormatKHR format = context->device.swapchain_support.formats[i]; - if (format.format == VK_FORMAT_B8G8R8A8_UNORM && - format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - out_swapchain->image_format = format; - found = true; - break; - } - } - if (!found) { - out_swapchain->image_format = context->device.swapchain_support.formats[0]; - } + vkCmdCopyBuffer(temp_cmd_buf.handle, source, dest, 1, ©_region); - VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; // guaranteed to be implemented - // TODO: look for mailbox - https://youtu.be/jWKVb_QdSNM?si=bHcd3sEf-M0x3QwH&t=1687 - - // TODO: requery swapchain support - - u32 image_count = context->device.swapchain_support.capabilities.minImageCount; - - VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; - swapchain_create_info.surface = context->surface; - swapchain_create_info.minImageCount = image_count; - swapchain_create_info.imageFormat = out_swapchain->image_format.format; - swapchain_create_info.imageColorSpace = out_swapchain->image_format.colorSpace; - DEBUG("Image extent %d %d\n", swapchain_extent.width, swapchain_extent.height); - swapchain_create_info.imageExtent = swapchain_extent; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 0; - swapchain_create_info.pQueueFamilyIndices = 0; - - swapchain_create_info.preTransform = - context->device.swapchain_support.capabilities.currentTransform; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = present_mode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = 0; - - TRACE("Create swapchain"); - VK_CHECK(vkCreateSwapchainKHR(context->device.logical_device, &swapchain_create_info, - context->allocator, &out_swapchain->handle)); - - context->current_frame = 0; - - // images - out_swapchain->image_count = 0; - vkGetSwapchainImagesKHR(context->device.logical_device, out_swapchain->handle, - &out_swapchain->image_count, 0); - - if (!out_swapchain->images) { - out_swapchain->images = (VkImage*)malloc(sizeof(VkImage) * out_swapchain->image_count); - } - if (!out_swapchain->views) { - out_swapchain->views = (VkImageView*)malloc(sizeof(VkImage) * out_swapchain->image_count); + vulkan_command_buffer_end_oneshot(context, pool, &temp_cmd_buf, queue); } - VK_CHECK(vkGetSwapchainImagesKHR(context->device.logical_device, out_swapchain->handle, - &out_swapchain->image_count, out_swapchain->images)); - - // views - for (int i = 0; i < out_swapchain->image_count; i++) { - VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - view_info.image = out_swapchain->images[i]; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = out_swapchain->image_format.format; - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_info.subresourceRange.baseMipLevel = 0; - view_info.subresourceRange.levelCount = 1; - view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = 1; - - VK_CHECK(vkCreateImageView(context->device.logical_device, &view_info, context->allocator, - &out_swapchain->views[i])); + + void vulkan_swapchain_create(vulkan_context * context, u32 width, u32 height, + vulkan_swapchain * out_swapchain) { + VkExtent2D swapchain_extent = { width, height }; + out_swapchain->max_frames_in_flight = 2; // support triple buffering + + // find a format + bool found; + for (u32 i = 0; i < context->device.swapchain_support.format_count; i++) { + VkSurfaceFormatKHR format = context->device.swapchain_support.formats[i]; + if (format.format == VK_FORMAT_B8G8R8A8_UNORM && + format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + out_swapchain->image_format = format; + found = true; + break; + } + } + if (!found) { + out_swapchain->image_format = context->device.swapchain_support.formats[0]; + } + + VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; // guaranteed to be implemented + // TODO: look for mailbox - https://youtu.be/jWKVb_QdSNM?si=bHcd3sEf-M0x3QwH&t=1687 + + // TODO: requery swapchain support + + u32 image_count = context->device.swapchain_support.capabilities.minImageCount; + + VkSwapchainCreateInfoKHR swapchain_create_info = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR + }; + swapchain_create_info.surface = context->surface; + swapchain_create_info.minImageCount = image_count; + swapchain_create_info.imageFormat = out_swapchain->image_format.format; + swapchain_create_info.imageColorSpace = out_swapchain->image_format.colorSpace; + DEBUG("Image extent %d %d\n", swapchain_extent.width, swapchain_extent.height); + swapchain_create_info.imageExtent = swapchain_extent; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = 0; + + swapchain_create_info.preTransform = + context->device.swapchain_support.capabilities.currentTransform; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = present_mode; + swapchain_create_info.clipped = VK_TRUE; + swapchain_create_info.oldSwapchain = 0; + + TRACE("Create swapchain"); + VK_CHECK(vkCreateSwapchainKHR(context->device.logical_device, &swapchain_create_info, + context->allocator, &out_swapchain->handle)); + + context->current_frame = 0; + + // images + out_swapchain->image_count = 0; + vkGetSwapchainImagesKHR(context->device.logical_device, out_swapchain->handle, + &out_swapchain->image_count, 0); + + if (!out_swapchain->images) { + out_swapchain->images = (VkImage*)malloc(sizeof(VkImage) * out_swapchain->image_count); + } + if (!out_swapchain->views) { + out_swapchain->views = (VkImageView*)malloc(sizeof(VkImage) * out_swapchain->image_count); + } + VK_CHECK(vkGetSwapchainImagesKHR(context->device.logical_device, out_swapchain->handle, + &out_swapchain->image_count, out_swapchain->images)); + + // views + for (int i = 0; i < out_swapchain->image_count; i++) { + VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_info.image = out_swapchain->images[i]; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = out_swapchain->image_format.format; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_info.subresourceRange.baseMipLevel = 0; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.baseArrayLayer = 0; + view_info.subresourceRange.layerCount = 1; + + VK_CHECK(vkCreateImageView(context->device.logical_device, &view_info, context->allocator, + &out_swapchain->views[i])); + } + + // depth attachment + if (!vulkan_device_detect_depth_format(&context->device)) { + ERROR_EXIT("Failed to find a supported depth format"); + } + vulkan_image_create(context, VK_IMAGE_TYPE_2D, swapchain_extent.width, swapchain_extent.height, + context->device.depth_format, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_DEPTH_BIT, + &out_swapchain->depth_attachment); + INFO("Depth attachment created"); + + INFO("Swapchain created successfully"); } - // depth attachment - if (!vulkan_device_detect_depth_format(&context->device)) { - ERROR_EXIT("Failed to find a supported depth format"); + // TODO: swapchain destroy + void vulkan_swapchain_recreate(vulkan_context * context, u32 width, u32 height, + vulkan_swapchain * swapchain) { + // TODO } - vulkan_image_create(context, VK_IMAGE_TYPE_2D, swapchain_extent.width, swapchain_extent.height, - context->device.depth_format, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_DEPTH_BIT, - &out_swapchain->depth_attachment); - INFO("Depth attachment created"); - - INFO("Swapchain created successfully"); -} + bool vulkan_swapchain_acquire_next_image_index( + vulkan_context * context, vulkan_swapchain * swapchain, u64 timeout_ns, + VkSemaphore image_available_semaphore, VkFence fence, u32 * out_image_index) { + VkResult result = + vkAcquireNextImageKHR(context->device.logical_device, swapchain->handle, timeout_ns, + image_available_semaphore, fence, out_image_index); -// TODO: swapchain destroy -void vulkan_swapchain_recreate(vulkan_context* context, u32 width, u32 height, - vulkan_swapchain* swapchain) { - // TODO -} -bool vulkan_swapchain_acquire_next_image_index(vulkan_context* context, vulkan_swapchain* swapchain, - u64 timeout_ns, - VkSemaphore image_available_semaphore, VkFence fence, - u32* out_image_index) { - VkResult result = - vkAcquireNextImageKHR(context->device.logical_device, swapchain->handle, timeout_ns, - image_available_semaphore, fence, out_image_index); + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + FATAL("Failed to acquire swapchain image"); + return false; + } - if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { - FATAL("Failed to acquire swapchain image"); - return false; + return true; } - return true; -} - -void vulkan_swapchain_present(vulkan_context* context, vulkan_swapchain* swapchain, - VkQueue graphics_queue, VkQueue present_queue, - VkSemaphore render_complete_semaphore, u32 present_image_index) { - // return image to swapchain for presentation - VkPresentInfoKHR present_info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &render_complete_semaphore; - present_info.swapchainCount = 1; - present_info.pSwapchains = &swapchain->handle; - present_info.pImageIndices = &present_image_index; - present_info.pResults = 0; - - VkResult result = vkQueuePresentKHR(present_queue, &present_info); - if (result != VK_SUCCESS) { - if (result == VK_SUBOPTIMAL_KHR) { - // WARN("Swapchain suboptimal - maybe resize needed?"); - } else { - FATAL("Failed to present swapchain iamge"); + void vulkan_swapchain_present(vulkan_context * context, vulkan_swapchain * swapchain, + VkQueue graphics_queue, VkQueue present_queue, + VkSemaphore render_complete_semaphore, u32 present_image_index) { + // return image to swapchain for presentation + VkPresentInfoKHR present_info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = &render_complete_semaphore; + present_info.swapchainCount = 1; + present_info.pSwapchains = &swapchain->handle; + present_info.pImageIndices = &present_image_index; + present_info.pResults = 0; + + VkResult result = vkQueuePresentKHR(present_queue, &present_info); + if (result != VK_SUCCESS) { + if (result == VK_SUBOPTIMAL_KHR) { + // WARN("Swapchain suboptimal - maybe resize needed?"); + } else { + FATAL("Failed to present swapchain iamge"); + } } + + // advance the current frame + context->current_frame = (context->current_frame + 1) % swapchain->max_frames_in_flight; } - // advance the current frame - context->current_frame = (context->current_frame + 1) % swapchain->max_frames_in_flight; -} + void vulkan_renderpass_create(vulkan_context * context, vulkan_renderpass * out_renderpass, + vec4 render_area, vec4 clear_colour, f32 depth, u32 stencil) { + out_renderpass->render_area = render_area; + out_renderpass->clear_colour = clear_colour; + out_renderpass->depth = depth; + out_renderpass->stencil = stencil; + + // main subpass + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + + // attachments + u32 attachment_desc_count = 2; + VkAttachmentDescription attachment_descriptions[2]; + + // Colour attachment + VkAttachmentDescription color_attachment; + color_attachment.format = context->swapchain.image_format.format; + color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + color_attachment.flags = 0; + + attachment_descriptions[0] = color_attachment; + + VkAttachmentReference color_attachment_reference; + color_attachment_reference.attachment = 0; + color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_reference; + + // Depth attachment + VkAttachmentDescription depth_attachment; + depth_attachment.format = context->device.depth_format; + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_attachment.flags = 0; + + attachment_descriptions[1] = depth_attachment; + + VkAttachmentReference depth_attachment_reference; + depth_attachment_reference.attachment = 1; + depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + subpass.pDepthStencilAttachment = &depth_attachment_reference; + + // TODO: other attachment styles + + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = 0; + subpass.pResolveAttachments = 0; + subpass.preserveAttachmentCount = 0; + subpass.preserveAttachmentCount = 0; + + // renderpass dependencies + VkSubpassDependency dependency; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependency.dependencyFlags = 0; + + VkRenderPassCreateInfo render_pass_create_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; + render_pass_create_info.attachmentCount = attachment_desc_count; + render_pass_create_info.pAttachments = attachment_descriptions; + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &subpass; + render_pass_create_info.dependencyCount = 1; + render_pass_create_info.pDependencies = &dependency; + render_pass_create_info.pNext = 0; + render_pass_create_info.flags = 0; + + VK_CHECK(vkCreateRenderPass(context->device.logical_device, &render_pass_create_info, + context->allocator, &out_renderpass->handle)); + } -void vulkan_renderpass_create(vulkan_context* context, vulkan_renderpass* out_renderpass, - vec4 render_area, vec4 clear_colour, f32 depth, u32 stencil) { - out_renderpass->render_area = render_area; - out_renderpass->clear_colour = clear_colour; - out_renderpass->depth = depth; - out_renderpass->stencil = stencil; - - // main subpass - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - - // attachments - u32 attachment_desc_count = 2; - VkAttachmentDescription attachment_descriptions[2]; - - // Colour attachment - VkAttachmentDescription color_attachment; - color_attachment.format = context->swapchain.image_format.format; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - color_attachment.flags = 0; - - attachment_descriptions[0] = color_attachment; - - VkAttachmentReference color_attachment_reference; - color_attachment_reference.attachment = 0; - color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_reference; - - // Depth attachment - VkAttachmentDescription depth_attachment; - depth_attachment.format = context->device.depth_format; - depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - depth_attachment.flags = 0; - - attachment_descriptions[1] = depth_attachment; - - VkAttachmentReference depth_attachment_reference; - depth_attachment_reference.attachment = 1; - depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - subpass.pDepthStencilAttachment = &depth_attachment_reference; - - // TODO: other attachment styles - - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = 0; - subpass.pResolveAttachments = 0; - subpass.preserveAttachmentCount = 0; - subpass.preserveAttachmentCount = 0; - - // renderpass dependencies - VkSubpassDependency dependency; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependency.dependencyFlags = 0; - - VkRenderPassCreateInfo render_pass_create_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; - render_pass_create_info.attachmentCount = attachment_desc_count; - render_pass_create_info.pAttachments = attachment_descriptions; - render_pass_create_info.subpassCount = 1; - render_pass_create_info.pSubpasses = &subpass; - render_pass_create_info.dependencyCount = 1; - render_pass_create_info.pDependencies = &dependency; - render_pass_create_info.pNext = 0; - render_pass_create_info.flags = 0; - - VK_CHECK(vkCreateRenderPass(context->device.logical_device, &render_pass_create_info, - context->allocator, &out_renderpass->handle)); -} + // TODO: renderpass destroy + + void vulkan_renderpass_begin(vulkan_command_buffer * command_buffer, + vulkan_renderpass * renderpass, VkFramebuffer framebuffer) { + VkRenderPassBeginInfo begin_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; + begin_info.renderPass = renderpass->handle; + begin_info.framebuffer = framebuffer; + begin_info.renderArea.offset.x = renderpass->render_area.x; + begin_info.renderArea.offset.y = renderpass->render_area.y; + begin_info.renderArea.extent.width = renderpass->render_area.z; + begin_info.renderArea.extent.height = renderpass->render_area.w; + + VkClearValue clear_values[2]; + memset(&clear_values, 0, sizeof(VkClearValue) * 2); + clear_values[0].color.float32[0] = renderpass->clear_colour.x; + clear_values[0].color.float32[1] = renderpass->clear_colour.y; + clear_values[0].color.float32[2] = renderpass->clear_colour.z; + clear_values[0].color.float32[3] = renderpass->clear_colour.w; + clear_values[1].depthStencil.depth = renderpass->depth; + clear_values[1].depthStencil.stencil = renderpass->stencil; + + begin_info.clearValueCount = 2; + begin_info.pClearValues = clear_values; + + vkCmdBeginRenderPass(command_buffer->handle, &begin_info, VK_SUBPASS_CONTENTS_INLINE); + command_buffer->state = COMMAND_BUFFER_STATE_IN_RENDER_PASS; + } -// TODO: renderpass destroy - -void vulkan_renderpass_begin(vulkan_command_buffer* command_buffer, vulkan_renderpass* renderpass, - VkFramebuffer framebuffer) { - VkRenderPassBeginInfo begin_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; - begin_info.renderPass = renderpass->handle; - begin_info.framebuffer = framebuffer; - begin_info.renderArea.offset.x = renderpass->render_area.x; - begin_info.renderArea.offset.y = renderpass->render_area.y; - begin_info.renderArea.extent.width = renderpass->render_area.z; - begin_info.renderArea.extent.height = renderpass->render_area.w; - - VkClearValue clear_values[2]; - memset(&clear_values, 0, sizeof(VkClearValue) * 2); - clear_values[0].color.float32[0] = renderpass->clear_colour.x; - clear_values[0].color.float32[1] = renderpass->clear_colour.y; - clear_values[0].color.float32[2] = renderpass->clear_colour.z; - clear_values[0].color.float32[3] = renderpass->clear_colour.w; - clear_values[1].depthStencil.depth = renderpass->depth; - clear_values[1].depthStencil.stencil = renderpass->stencil; - - begin_info.clearValueCount = 2; - begin_info.pClearValues = clear_values; - - vkCmdBeginRenderPass(command_buffer->handle, &begin_info, VK_SUBPASS_CONTENTS_INLINE); - command_buffer->state = COMMAND_BUFFER_STATE_IN_RENDER_PASS; -} + void vulkan_renderpass_end(vulkan_command_buffer * command_buffer, + vulkan_renderpass * renderpass) { + vkCmdEndRenderPass(command_buffer->handle); + command_buffer->state = COMMAND_BUFFER_STATE_RECORDING; + } -void vulkan_renderpass_end(vulkan_command_buffer* command_buffer, vulkan_renderpass* renderpass) { - vkCmdEndRenderPass(command_buffer->handle); - command_buffer->state = COMMAND_BUFFER_STATE_RECORDING; -} + bool create_buffers(vulkan_context * context) { + VkMemoryPropertyFlagBits mem_prop_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; -bool create_buffers(vulkan_context* context) { - VkMemoryPropertyFlagBits mem_prop_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + const u64 vertex_buffer_size = sizeof(vertex_pos) * 1024 * 1024; + if (!vulkan_buffer_create(context, vertex_buffer_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + mem_prop_flags, true, &context->object_vertex_buffer)) { + ERROR("couldnt create vertex buffer"); + return false; + } - const u64 vertex_buffer_size = sizeof(vertex_pos) * 1024 * 1024; - if (!vulkan_buffer_create(context, vertex_buffer_size, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT, - mem_prop_flags, true, &context->object_vertex_buffer)) { - ERROR("couldnt create vertex buffer"); - return false; - } + context->geometry_vertex_offset = 0; - context->geometry_vertex_offset = 0; + const u64 index1_buffer_size = sizeof(u32) * 1024 * 1024; + if (!vulkan_buffer_create(context, index1_buffer_size, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + mem_prop_flags, true, &context->object_index_buffer)) { + ERROR("couldnt create vertex buffer"); + return false; + } + context->geometry_index_offset = 0; - const u64 index1_buffer_size = sizeof(u32) * 1024 * 1024; - if (!vulkan_buffer_create(context, index1_buffer_size, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT, - mem_prop_flags, true, &context->object_index_buffer)) { - ERROR("couldnt create vertex buffer"); - return false; + return true; } - context->geometry_index_offset = 0; - return true; -} + void create_command_buffers(renderer * ren) { + if (!context.gfx_command_buffers) { + context.gfx_command_buffers = vulkan_command_buffer_darray_new(context.swapchain.image_count); + } -void create_command_buffers(renderer* ren) { - if (!context.gfx_command_buffers) { - context.gfx_command_buffers = vulkan_command_buffer_darray_new(context.swapchain.image_count); + for (u32 i = 0; i < context.swapchain.image_count; i++) { + vulkan_command_buffer_allocate(&context, context.device.gfx_command_pool, true, + &context.gfx_command_buffers->data[i]); + } } - for (u32 i = 0; i < context.swapchain.image_count; i++) { - vulkan_command_buffer_allocate(&context, context.device.gfx_command_pool, true, - &context.gfx_command_buffers->data[i]); + void upload_data_range(vulkan_context * context, VkCommandPool pool, VkFence fence, VkQueue queue, + vulkan_buffer * buffer, u64 offset, u64 size, void* data) { + VkBufferUsageFlags flags = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + vulkan_buffer staging; + vulkan_buffer_create(context, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, flags, true, &staging); + // load data into staging buffer + printf("Size: %ld\n", size); + vulkan_buffer_load_data(context, &staging, 0, size, 0, data); + + // copy + vulkan_buffer_copy_to(context, pool, fence, queue, staging.handle, 0, buffer->handle, offset, + size); + + vkDestroyBuffer(context->device.logical_device, staging.handle, context->allocator); } -} -void upload_data_range(vulkan_context* context, VkCommandPool pool, VkFence fence, VkQueue queue, - vulkan_buffer* buffer, u64 offset, u64 size, void* data) { - VkBufferUsageFlags flags = - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - vulkan_buffer staging; - vulkan_buffer_create(context, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, flags, true, &staging); - // load data into staging buffer - printf("Size: %ld\n", size); - vulkan_buffer_load_data(context, &staging, 0, size, 0, data); - - // copy - vulkan_buffer_copy_to(context, pool, fence, queue, staging.handle, 0, buffer->handle, offset, - size); - - vkDestroyBuffer(context->device.logical_device, staging.handle, context->allocator); -} - -void regenerate_framebuffers(renderer* ren, vulkan_swapchain* swapchain, - vulkan_renderpass* renderpass) { - for (u32 i = 0; i < swapchain->image_count; i++) { - u32 attachment_count = 2; // one for depth, one for colour - - VkImageView attachments[2] = { swapchain->views[i], swapchain->depth_attachment.view }; + void regenerate_framebuffers(renderer * ren, vulkan_swapchain * swapchain, + vulkan_renderpass * renderpass) { + for (u32 i = 0; i < swapchain->image_count; i++) { + u32 attachment_count = 2; // one for depth, one for colour - vulkan_framebuffer_create(&context, renderpass, context.framebuffer_width, - context.framebuffer_height, 2, attachments, - &swapchain->framebuffers->data[i]); - } -} + VkImageView attachments[2] = { swapchain->views[i], swapchain->depth_attachment.view }; -void vulkan_fence_create(vulkan_context* context, bool create_signaled, vulkan_fence* out_fence) { - out_fence->is_signaled = create_signaled; - VkFenceCreateInfo fence_create_info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; - if (out_fence->is_signaled) { - fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + vulkan_framebuffer_create(&context, renderpass, context.framebuffer_width, + context.framebuffer_height, 2, attachments, + &swapchain->framebuffers->data[i]); + } } - vkCreateFence(context->device.logical_device, &fence_create_info, context->allocator, - &out_fence->handle); -} + void vulkan_fence_create(vulkan_context * context, bool create_signaled, + vulkan_fence* out_fence) { + out_fence->is_signaled = create_signaled; + VkFenceCreateInfo fence_create_info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + if (out_fence->is_signaled) { + fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + } -// TODO: vulkan_fence_destroy + vkCreateFence(context->device.logical_device, &fence_create_info, context->allocator, + &out_fence->handle); + } -bool vulkan_fence_wait(vulkan_context* context, vulkan_fence* fence, u64 timeout_ns) { - if (!fence->is_signaled) { - VkResult result = - vkWaitForFences(context->device.logical_device, 1, &fence->handle, true, timeout_ns); - switch (result) { - case VK_SUCCESS: - fence->is_signaled = true; - return true; - case VK_TIMEOUT: - WARN("vk_fence_wait - Timed out"); - break; - default: - ERROR("vk_fence_wait - Unhanlded error type"); - break; + // TODO: vulkan_fence_destroy + + bool vulkan_fence_wait(vulkan_context * context, vulkan_fence * fence, u64 timeout_ns) { + if (!fence->is_signaled) { + VkResult result = + vkWaitForFences(context->device.logical_device, 1, &fence->handle, true, timeout_ns); + switch (result) { + case VK_SUCCESS: + fence->is_signaled = true; + return true; + case VK_TIMEOUT: + WARN("vk_fence_wait - Timed out"); + break; + default: + ERROR("vk_fence_wait - Unhanlded error type"); + break; + } + } else { + return true; } - } else { - return true; - } - return false; -} -void vulkan_fence_reset(vulkan_context* context, vulkan_fence* fence) { - if (fence->is_signaled) { - vkResetFences(context->device.logical_device, 1, &fence->handle); - fence->is_signaled = false; + return false; + } + void vulkan_fence_reset(vulkan_context * context, vulkan_fence * fence) { + if (fence->is_signaled) { + vkResetFences(context->device.logical_device, 1, &fence->handle); + fence->is_signaled = false; + } } -} -bool gfx_backend_init(renderer* ren) { - INFO("loading Vulkan backend"); + bool gfx_backend_init(renderer * ren) { + INFO("loading Vulkan backend"); - vulkan_state* internal = malloc(sizeof(vulkan_state)); - ren->backend_state = (void*)internal; + vulkan_state* internal = malloc(sizeof(vulkan_state)); + ren->backend_state = (void*)internal; - context.allocator = 0; // TODO: custom allocator + context.allocator = 0; // TODO: custom allocator - context.framebuffer_width = SCR_WIDTH; - context.framebuffer_height = SCR_HEIGHT; + context.framebuffer_width = SCR_WIDTH; + context.framebuffer_height = SCR_HEIGHT; - // Setup Vulkan instance - VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; - app_info.apiVersion = VK_API_VERSION_1_3; - app_info.pApplicationName = ren->config.window_name; - app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - app_info.pEngineName = "Celeritas Engine"; - app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); + // Setup Vulkan instance + VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + app_info.apiVersion = VK_API_VERSION_1_3; + app_info.pApplicationName = ren->config.window_name; + app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + app_info.pEngineName = "Celeritas Engine"; + app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); - VkInstanceCreateInfo create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; - create_info.pApplicationInfo = &app_info; + VkInstanceCreateInfo create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + create_info.pApplicationInfo = &app_info; - cstr_darray* required_extensions = cstr_darray_new(2); - cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); + cstr_darray* required_extensions = cstr_darray_new(2); + cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); - plat_get_required_extension_names(required_extensions); + plat_get_required_extension_names(required_extensions); #if defined(CDEBUG) - cstr_darray_push(required_extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + cstr_darray_push(required_extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - DEBUG("Required extensions:"); - for (u32 i = 0; i < cstr_darray_len(required_extensions); i++) { - DEBUG(" %s", required_extensions->data[i]); - } + DEBUG("Required extensions:"); + for (u32 i = 0; i < cstr_darray_len(required_extensions); i++) { + DEBUG(" %s", required_extensions->data[i]); + } #endif - create_info.enabledExtensionCount = cstr_darray_len(required_extensions); - create_info.ppEnabledExtensionNames = required_extensions->data; + create_info.enabledExtensionCount = cstr_darray_len(required_extensions); + create_info.ppEnabledExtensionNames = required_extensions->data; - // Validation layers - create_info.enabledLayerCount = 0; - create_info.ppEnabledLayerNames = 0; + // Validation layers + create_info.enabledLayerCount = 0; + create_info.ppEnabledLayerNames = 0; #if defined(CDEBUG) - INFO("Validation layers enabled"); - cstr_darray* desired_validation_layers = cstr_darray_new(1); - cstr_darray_push(desired_validation_layers, "VK_LAYER_KHRONOS_validation"); - - u32 n_available_layers = 0; - VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, 0)); - TRACE("%d available layers", n_available_layers); - VkLayerProperties_darray* available_layers = VkLayerProperties_darray_new(n_available_layers); - VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, available_layers->data)); - - for (int i = 0; i < cstr_darray_len(desired_validation_layers); i++) { - // look through layers to make sure we can find the ones we want - bool found = false; - for (int j = 0; j < n_available_layers; j++) { - if (str8_equals(str8_cstr_view(desired_validation_layers->data[i]), - str8_cstr_view(available_layers->data[j].layerName))) { - found = true; - TRACE("Found layer %s", desired_validation_layers->data[i]); - break; + INFO("Validation layers enabled"); + cstr_darray* desired_validation_layers = cstr_darray_new(1); + cstr_darray_push(desired_validation_layers, "VK_LAYER_KHRONOS_validation"); + + u32 n_available_layers = 0; + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, 0)); + TRACE("%d available layers", n_available_layers); + VkLayerProperties_darray* available_layers = VkLayerProperties_darray_new(n_available_layers); + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, available_layers->data)); + + for (int i = 0; i < cstr_darray_len(desired_validation_layers); i++) { + // look through layers to make sure we can find the ones we want + bool found = false; + for (int j = 0; j < n_available_layers; j++) { + if (str8_equals(str8_cstr_view(desired_validation_layers->data[i]), + str8_cstr_view(available_layers->data[j].layerName))) { + found = true; + TRACE("Found layer %s", desired_validation_layers->data[i]); + break; + } } - } - if (!found) { - FATAL("Required validation is missing %s", desired_validation_layers->data[i]); - return false; + if (!found) { + FATAL("Required validation is missing %s", desired_validation_layers->data[i]); + return false; + } } - } - INFO("All validation layers are present"); - create_info.enabledLayerCount = cstr_darray_len(desired_validation_layers); - create_info.ppEnabledLayerNames = desired_validation_layers->data; + INFO("All validation layers are present"); + create_info.enabledLayerCount = cstr_darray_len(desired_validation_layers); + create_info.ppEnabledLayerNames = desired_validation_layers->data; #endif - VkResult result = vkCreateInstance(&create_info, NULL, &context.instance); - if (result != VK_SUCCESS) { - ERROR("vkCreateInstance failed with result: %u", result); - return false; - } + VkResult result = vkCreateInstance(&create_info, NULL, &context.instance); + if (result != VK_SUCCESS) { + ERROR("vkCreateInstance failed with result: %u", result); + return false; + } - // Debugger + // Debugger #if defined(CDEBUG) - DEBUG("Creating Vulkan debugger") - u32 log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; - VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { - VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT - }; - debug_create_info.messageSeverity = log_severity; - debug_create_info.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; - debug_create_info.pfnUserCallback = vk_debug_callback; - - PFN_vkCreateDebugUtilsMessengerEXT func = - (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance, - "vkCreateDebugUtilsMessengerEXT"); - assert(func); - VK_CHECK(func(context.instance, &debug_create_info, context.allocator, &context.vk_debugger)); - DEBUG("Vulkan debugger created"); + DEBUG("Creating Vulkan debugger") + u32 log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT + }; + debug_create_info.messageSeverity = log_severity; + debug_create_info.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; + debug_create_info.pfnUserCallback = vk_debug_callback; + + PFN_vkCreateDebugUtilsMessengerEXT func = + (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance, + "vkCreateDebugUtilsMessengerEXT"); + assert(func); + VK_CHECK(func(context.instance, &debug_create_info, context.allocator, &context.vk_debugger)); + DEBUG("Vulkan debugger created"); #endif - // Surface creation - DEBUG("Create SurfaceKHR") - VkSurfaceKHR surface; - VK_CHECK(glfwCreateWindowSurface(context.instance, ren->window, NULL, &surface)); - context.surface = surface; - DEBUG("Vulkan surface created") + // Surface creation + DEBUG("Create SurfaceKHR") + VkSurfaceKHR surface; + VK_CHECK(glfwCreateWindowSurface(context.instance, ren->window, NULL, &surface)); + context.surface = surface; + DEBUG("Vulkan surface created") - // Device creation - if (!vulkan_device_create(&context)) { - FATAL("device creation failed"); - return false; - } - - // Swapchain creation - vulkan_swapchain_create(&context, SCR_WIDTH, SCR_HEIGHT, &context.swapchain); - - // Renderpass creation - vulkan_renderpass_create(&context, &context.main_renderpass, - vec4(0, 0, context.framebuffer_width, context.framebuffer_height), - rgba_to_vec4(COLOUR_SEA_GREEN), 1.0, 0); - - // Framebiffers creation - context.swapchain.framebuffers = vulkan_framebuffer_darray_new(context.swapchain.image_count); - regenerate_framebuffers(ren, &context.swapchain, &context.main_renderpass); - INFO("Framebuffers created"); - - // Command buffers creation - create_command_buffers(ren); - INFO("Command buffers created"); - - // Sync objects - context.image_available_semaphores = - calloc(context.swapchain.max_frames_in_flight, sizeof(VkSemaphore)); - context.queue_complete_semaphores = - calloc(context.swapchain.max_frames_in_flight, sizeof(VkSemaphore)); - context.in_flight_fences = calloc(context.swapchain.max_frames_in_flight, sizeof(vulkan_fence)); - - for (u8 i = 0; i < context.swapchain.max_frames_in_flight; i++) { - VkSemaphoreCreateInfo semaphore_create_info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - vkCreateSemaphore(context.device.logical_device, &semaphore_create_info, context.allocator, - &context.image_available_semaphores[i]); - vkCreateSemaphore(context.device.logical_device, &semaphore_create_info, context.allocator, - &context.queue_complete_semaphores[i]); - - // create the fence in a signaled state - vulkan_fence_create(&context, true, &context.in_flight_fences[i]); - } + // Device creation + if (!vulkan_device_create(&context)) { + FATAL("device creation failed"); + return false; + } - context.images_in_flight = malloc(sizeof(vulkan_fence*) * context.swapchain.max_frames_in_flight); - for (u8 i = 0; i < context.swapchain.max_frames_in_flight; i++) { - context.images_in_flight[i] = 0; - } - INFO("Sync objects created"); + // Swapchain creation + vulkan_swapchain_create(&context, SCR_WIDTH, SCR_HEIGHT, &context.swapchain); + + // Renderpass creation + vulkan_renderpass_create(&context, &context.main_renderpass, + vec4(0, 0, context.framebuffer_width, context.framebuffer_height), + rgba_to_vec4(COLOUR_SEA_GREEN), 1.0, 0); + + // Framebiffers creation + context.swapchain.framebuffers = vulkan_framebuffer_darray_new(context.swapchain.image_count); + regenerate_framebuffers(ren, &context.swapchain, &context.main_renderpass); + INFO("Framebuffers created"); + + // Command buffers creation + create_command_buffers(ren); + INFO("Command buffers created"); + + // Sync objects + context.image_available_semaphores = + calloc(context.swapchain.max_frames_in_flight, sizeof(VkSemaphore)); + context.queue_complete_semaphores = + calloc(context.swapchain.max_frames_in_flight, sizeof(VkSemaphore)); + context.in_flight_fences = calloc(context.swapchain.max_frames_in_flight, sizeof(vulkan_fence)); + + for (u8 i = 0; i < context.swapchain.max_frames_in_flight; i++) { + VkSemaphoreCreateInfo semaphore_create_info = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + vkCreateSemaphore(context.device.logical_device, &semaphore_create_info, context.allocator, + &context.image_available_semaphores[i]); + vkCreateSemaphore(context.device.logical_device, &semaphore_create_info, context.allocator, + &context.queue_complete_semaphores[i]); + + // create the fence in a signaled state + vulkan_fence_create(&context, true, &context.in_flight_fences[i]); + } - // Shader modules - vulkan_object_shader_create(&context, &context.object_shader); - INFO("Compiled shader modules") + context.images_in_flight = + malloc(sizeof(vulkan_fence*) * context.swapchain.max_frames_in_flight); + for (u8 i = 0; i < context.swapchain.max_frames_in_flight; i++) { + context.images_in_flight[i] = 0; + } + INFO("Sync objects created"); - create_buffers(&context); - INFO("Created buffers"); + // Shader modules + vulkan_object_shader_create(&context, &context.object_shader); + INFO("Compiled shader modules") - // TODO: temporary test code + create_buffers(&context); + INFO("Created buffers"); - mesh cube = prim_cube_mesh_create(); + // TODO: temporary test code - vertex* verts = malloc(sizeof(vertex) * cube.vertices->len); + mesh cube = prim_cube_mesh_create(); - f32 scale = 3.0; - for (size_t i = 0; i < cube.vertices->len; i++) { - verts[i].position = vec3_mult(cube.vertices->data[i].position, scale); - verts[i].normal = cube.vertices->data[i].normal; - verts[i].uv = cube.vertices->data[i].uv; - } + vertex* verts = malloc(sizeof(vertex) * cube.vertices->len); - // const f32 s = 1.0; - // const u32 vert_count = 4; - // vertex_pos verts[4] = { 0 }; + f32 scale = 3.0; + for (size_t i = 0; i < cube.vertices->len; i++) { + verts[i].position = vec3_mult(cube.vertices->data[i].position, scale); + verts[i].normal = cube.vertices->data[i].normal; + verts[i].uv = cube.vertices->data[i].uv; + } - // verts[0].pos.x = -0.5 * s; - // verts[0].pos.y = -0.5 * s; + // const f32 s = 1.0; + // const u32 vert_count = 4; + // vertex_pos verts[4] = { 0 }; - // verts[1].pos.x = 0.5 * s; - // verts[1].pos.y = 0.5 * s; + // verts[0].pos.x = -0.5 * s; + // verts[0].pos.y = -0.5 * s; - // verts[2].pos.x = -0.5 * s; - // verts[2].pos.y = 0.5 * s; + // verts[1].pos.x = 0.5 * s; + // verts[1].pos.y = 0.5 * s; - // verts[3].pos.x = 0.5 * s; - // verts[3].pos.y = -0.5 * s; + // verts[2].pos.x = -0.5 * s; + // verts[2].pos.y = 0.5 * s; - // const u32 index_count = 6; - // u32 indices[6] = { 0, 1, 2, 0, 3, 1 }; + // verts[3].pos.x = 0.5 * s; + // verts[3].pos.y = -0.5 * s; - upload_data_range(&context, context.device.gfx_command_pool, 0, context.device.graphics_queue, - &context.object_vertex_buffer, 0, sizeof(vertex) * cube.vertices->len, verts); - TRACE("Uploaded vertex data"); - upload_data_range(&context, context.device.gfx_command_pool, 0, context.device.graphics_queue, - &context.object_index_buffer, 0, sizeof(u32) * cube.indices_len, cube.indices); - TRACE("Uploaded index data"); - vertex_darray_free(cube.vertices); - free(cube.indices); + // const u32 index_count = 6; + // u32 indices[6] = { 0, 1, 2, 0, 3, 1 }; - // upload texture + upload_data_range(&context, context.device.gfx_command_pool, 0, context.device.graphics_queue, + &context.object_vertex_buffer, 0, sizeof(vertex) * cube.vertices->len, verts); + TRACE("Uploaded vertex data"); + upload_data_range(&context, context.device.gfx_command_pool, 0, context.device.graphics_queue, + &context.object_index_buffer, 0, sizeof(u32) * cube.indices_len, + cube.indices); + TRACE("Uploaded index data"); + vertex_darray_free(cube.vertices); + free(cube.indices); - // --- End test code + // upload texture - INFO("Vulkan renderer initialisation succeeded"); - return true; -} + // --- End test code -void gfx_backend_shutdown(renderer* ren) { - DEBUG("Destroying Vulkan debugger"); - if (context.vk_debugger) { - PFN_vkDestroyDebugUtilsMessengerEXT func = - (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - context.instance, "vkDestroyDebugUtilsMessengerEXT"); - func(context.instance, context.vk_debugger, context.allocator); + INFO("Vulkan renderer initialisation succeeded"); + return true; } - DEBUG("Destroying Vulkan instance..."); - vkDestroyInstance(context.instance, context.allocator); -} + void gfx_backend_shutdown(renderer * ren) { + DEBUG("Destroying Vulkan debugger"); + if (context.vk_debugger) { + PFN_vkDestroyDebugUtilsMessengerEXT func = + (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( + context.instance, "vkDestroyDebugUtilsMessengerEXT"); + func(context.instance, context.vk_debugger, context.allocator); + } -void backend_begin_frame(renderer* ren, f32 delta_time) { - vulkan_device* device = &context.device; + DEBUG("Destroying Vulkan instance..."); + vkDestroyInstance(context.instance, context.allocator); + } - // TODO: resize gubbins + void backend_begin_frame(renderer * ren, f32 delta_time) { + vulkan_device* device = &context.device; - if (!vulkan_fence_wait(&context, &context.in_flight_fences[context.current_frame], UINT64_MAX)) { - WARN("In-flight fence wait failure"); - } + // TODO: resize gubbins - if (!vulkan_swapchain_acquire_next_image_index( - &context, &context.swapchain, UINT64_MAX, - context.image_available_semaphores[context.current_frame], 0, &context.image_index)) { - WARN("couldnt acquire swapchain next image"); - } + if (!vulkan_fence_wait(&context, &context.in_flight_fences[context.current_frame], + UINT64_MAX)) { + WARN("In-flight fence wait failure"); + } - vulkan_command_buffer* command_buffer = &context.gfx_command_buffers->data[context.image_index]; - vulkan_command_buffer_reset(command_buffer); - vulkan_command_buffer_begin(command_buffer, false, false, false); + if (!vulkan_swapchain_acquire_next_image_index( + &context, &context.swapchain, UINT64_MAX, + context.image_available_semaphores[context.current_frame], 0, &context.image_index)) { + WARN("couldnt acquire swapchain next image"); + } - VkViewport viewport; - viewport.x = 0.0; - viewport.y = 0; - viewport.width = (f32)context.framebuffer_width; - viewport.height = (f32)context.framebuffer_height; - viewport.minDepth = 0.0; - viewport.maxDepth = 1.0; + vulkan_command_buffer* command_buffer = &context.gfx_command_buffers->data[context.image_index]; + vulkan_command_buffer_reset(command_buffer); + vulkan_command_buffer_begin(command_buffer, false, false, false); - VkRect2D scissor; - scissor.offset.x = scissor.offset.y = 0; - scissor.extent.width = context.framebuffer_width; - scissor.extent.height = context.framebuffer_height; + VkViewport viewport; + viewport.x = 0.0; + viewport.y = 0; + viewport.width = (f32)context.framebuffer_width; + viewport.height = (f32)context.framebuffer_height; + viewport.minDepth = 0.0; + viewport.maxDepth = 1.0; - vkCmdSetViewport(command_buffer->handle, 0, 1, &viewport); - vkCmdSetScissor(command_buffer->handle, 0, 1, &scissor); + VkRect2D scissor; + scissor.offset.x = scissor.offset.y = 0; + scissor.extent.width = context.framebuffer_width; + scissor.extent.height = context.framebuffer_height; - context.main_renderpass.render_area.z = context.framebuffer_width; - context.main_renderpass.render_area.w = context.framebuffer_height; + vkCmdSetViewport(command_buffer->handle, 0, 1, &viewport); + vkCmdSetScissor(command_buffer->handle, 0, 1, &scissor); - vulkan_renderpass_begin(command_buffer, &context.main_renderpass, - context.swapchain.framebuffers->data[context.image_index].handle); -} + context.main_renderpass.render_area.z = context.framebuffer_width; + context.main_renderpass.render_area.w = context.framebuffer_height; -void texture_data_upload(texture* tex) { - printf("Texture name %s\n", tex->name); - tex->backend_data = malloc(sizeof(vulkan_texture_data)); - vulkan_texture_data* data = (vulkan_texture_data*)tex->backend_data; - printf("Texture (%s) details: \n width %d\n height %d\n channel count %d\n", tex->name, - tex->width, tex->height, tex->channel_count); - VkDeviceSize image_size = tex->width * tex->height * max(tex->channel_count, 4); - - TRACE("Creating buffer of size %ld", image_size); - - VkFormat image_format = VK_FORMAT_R8G8B8A8_SRGB; - - VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - VkMemoryPropertyFlags memory_prop_flags = - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - vulkan_buffer staging; - vulkan_buffer_create(&context, image_size, usage, memory_prop_flags, true, &staging); - DEBUG("Uploading image data"); - vulkan_buffer_load_data(&context, &staging, 0, image_size, 0, tex->image_data); - INFO("Loaded iamge data!"); - - vulkan_image_create( - &context, VK_IMAGE_TYPE_2D, tex->width, tex->height, image_format, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_COLOR_BIT, &data->image); - - vulkan_command_buffer temp_buffer; - vulkan_command_buffer_allocate_and_begin_oneshot(&context, context.device.gfx_command_pool, - &temp_buffer); - - vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - vulkan_image_copy_from_buffer(&data->image, staging.handle, &temp_buffer); - - vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - vulkan_command_buffer_end_oneshot(&context, context.device.gfx_command_pool, &temp_buffer, - context.device.graphics_queue); - - VkSamplerCreateInfo sampler_info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; - sampler_info.magFilter = VK_FILTER_LINEAR; - sampler_info.minFilter = VK_FILTER_LINEAR; - sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler_info.anisotropyEnable = VK_TRUE; - sampler_info.maxAnisotropy = 16; - sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - sampler_info.unnormalizedCoordinates = VK_FALSE; - sampler_info.compareEnable = VK_FALSE; - sampler_info.compareOp = VK_COMPARE_OP_ALWAYS; - sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler_info.mipLodBias = 0.0; - sampler_info.minLod = 0.0; - sampler_info.maxLod = 0.0; - - VkResult res = vkCreateSampler(context.device.logical_device, &sampler_info, context.allocator, - &data->sampler); - if (res != VK_SUCCESS) { - ERROR("Error creating texture sampler for image %s", tex->name); - return; + vulkan_renderpass_begin(command_buffer, &context.main_renderpass, + context.swapchain.framebuffers->data[context.image_index].handle); } - tex->image_data = (void*)data; -} + void texture_data_upload(texture * tex) { + printf("Texture name %s\n", tex->name); + tex->backend_data = malloc(sizeof(vulkan_texture_data)); + vulkan_texture_data* data = (vulkan_texture_data*)tex->backend_data; + printf("Texture (%s) details: \n width %d\n height %d\n channel count %d\n", tex->name, + tex->width, tex->height, tex->channel_count); + VkDeviceSize image_size = tex->width * tex->height * max(tex->channel_count, 4); + + TRACE("Creating buffer of size %ld", image_size); + + VkFormat image_format = VK_FORMAT_R8G8B8A8_SRGB; + + VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + VkMemoryPropertyFlags memory_prop_flags = + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + vulkan_buffer staging; + vulkan_buffer_create(&context, image_size, usage, memory_prop_flags, true, &staging); + DEBUG("Uploading image data"); + vulkan_buffer_load_data(&context, &staging, 0, image_size, 0, tex->image_data); + INFO("Loaded iamge data!"); + + vulkan_image_create( + &context, VK_IMAGE_TYPE_2D, tex->width, tex->height, image_format, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_COLOR_BIT, &data->image); + + vulkan_command_buffer temp_buffer; + vulkan_command_buffer_allocate_and_begin_oneshot(&context, context.device.gfx_command_pool, + &temp_buffer); + + vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vulkan_image_copy_from_buffer(&data->image, staging.handle, &temp_buffer); + + vulkan_image_transition_layout(&context, &temp_buffer, &data->image, image_format, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + vulkan_command_buffer_end_oneshot(&context, context.device.gfx_command_pool, &temp_buffer, + context.device.graphics_queue); + + VkSamplerCreateInfo sampler_info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.anisotropyEnable = VK_TRUE; + sampler_info.maxAnisotropy = 16; + sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + sampler_info.unnormalizedCoordinates = VK_FALSE; + sampler_info.compareEnable = VK_FALSE; + sampler_info.compareOp = VK_COMPARE_OP_ALWAYS; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.mipLodBias = 0.0; + sampler_info.minLod = 0.0; + sampler_info.maxLod = 0.0; + + VkResult res = vkCreateSampler(context.device.logical_device, &sampler_info, context.allocator, + &data->sampler); + if (res != VK_SUCCESS) { + ERROR("Error creating texture sampler for image %s", tex->name); + return; + } -// TODO: destroy texture + tex->image_data = (void*)data; + } -void backend_end_frame(renderer* ren, f32 delta_time) { - vulkan_command_buffer* command_buffer = &context.gfx_command_buffers->data[context.image_index]; + // TODO: destroy texture - vulkan_renderpass_end(command_buffer, &context.main_renderpass); + void backend_end_frame(renderer * ren, f32 delta_time) { + vulkan_command_buffer* command_buffer = &context.gfx_command_buffers->data[context.image_index]; - vulkan_command_buffer_end(command_buffer); + vulkan_renderpass_end(command_buffer, &context.main_renderpass); - // TODO: wait on fence - https://youtu.be/hRL71D1f3pU?si=nLJx-ZsemDBeQiQ1&t=1037 + vulkan_command_buffer_end(command_buffer); - context.images_in_flight[context.image_index] = &context.in_flight_fences[context.current_frame]; + // TODO: wait on fence - https://youtu.be/hRL71D1f3pU?si=nLJx-ZsemDBeQiQ1&t=1037 - vulkan_fence_reset(&context, &context.in_flight_fences[context.current_frame]); + context.images_in_flight[context.image_index] = + &context.in_flight_fences[context.current_frame]; - VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &command_buffer->handle; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &context.queue_complete_semaphores[context.current_frame]; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &context.image_available_semaphores[context.current_frame]; + vulkan_fence_reset(&context, &context.in_flight_fences[context.current_frame]); - VkPipelineStageFlags flags[1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - submit_info.pWaitDstStageMask = flags; + VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer->handle; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &context.queue_complete_semaphores[context.current_frame]; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &context.image_available_semaphores[context.current_frame]; - VkResult result = vkQueueSubmit(context.device.graphics_queue, 1, &submit_info, - context.in_flight_fences[context.current_frame].handle); + VkPipelineStageFlags flags[1] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + submit_info.pWaitDstStageMask = flags; - if (result != VK_SUCCESS) { - ERROR("queue submission failed. fark."); - } + VkResult result = vkQueueSubmit(context.device.graphics_queue, 1, &submit_info, + context.in_flight_fences[context.current_frame].handle); - vulkan_command_buffer_update_submitted(command_buffer); + if (result != VK_SUCCESS) { + ERROR("queue submission failed. fark."); + } - vulkan_swapchain_present( - &context, &context.swapchain, context.device.graphics_queue, context.device.graphics_queue, - context.queue_complete_semaphores[context.current_frame], context.image_index); -} + vulkan_command_buffer_update_submitted(command_buffer); -void gfx_backend_draw_frame(renderer* ren, camera* cam, mat4 model, texture* tex) { - backend_begin_frame(ren, 16.0); + vulkan_swapchain_present( + &context, &context.swapchain, context.device.graphics_queue, context.device.graphics_queue, + context.queue_complete_semaphores[context.current_frame], context.image_index); + } - mat4 proj; - mat4 view; + void gfx_backend_draw_frame(renderer * ren, camera * cam, mat4 model, texture * tex) { + backend_begin_frame(ren, 16.0); - camera_view_projection(cam, SCR_HEIGHT, SCR_WIDTH, &view, &proj); + mat4 proj; + mat4 view; - context.object_shader.texture_data = (vulkan_texture_data*)tex->image_data; - gfx_backend_update_global_state(proj, view, cam->position, vec4(1.0, 1.0, 1.0, 1.0), 0); + camera_view_projection(cam, SCR_HEIGHT, SCR_WIDTH, &view, &proj); - vulkan_object_shader_update_object(&context, &context.object_shader, model); + context.object_shader.texture_data = (vulkan_texture_data*)tex->image_data; + gfx_backend_update_global_state(proj, view, cam->position, vec4(1.0, 1.0, 1.0, 1.0), 0); - backend_end_frame(ren, 16.0); -} + vulkan_object_shader_update_object(&context, &context.object_shader, model); -void gfx_backend_update_global_state(mat4 projection, mat4 view, vec3 view_pos, vec4 ambient_colour, - i32 mode) { - vulkan_object_shader_use(&context, &context.object_shader); + backend_end_frame(ren, 16.0); + } - vulkan_object_shader_update_global_state(&context, &context.object_shader); - context.object_shader.global_ubo.projection = projection; - context.object_shader.global_ubo.view = view; - // TODO: other UBO properties -} + void gfx_backend_update_global_state(mat4 projection, mat4 view, vec3 view_pos, + vec4 ambient_colour, i32 mode) { + vulkan_object_shader_use(&context, &context.object_shader); -void clear_screen(vec3 colour) {} + vulkan_object_shader_update_global_state(&context, &context.object_shader); + context.object_shader.global_ubo.projection = projection; + context.object_shader.global_ubo.view = view; + // TODO: other UBO properties + } -void bind_texture(shader s, texture* tex, u32 slot) {} -void bind_mesh_vertex_buffer(void* backend, mesh* mesh) {} -void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) {} + void clear_screen(vec3 colour) {} -shader shader_create_separate(const char* vert_shader, const char* frag_shader) {} -void set_shader(shader s) {} + void bind_texture(shader s, texture * tex, u32 slot) {} + void bind_mesh_vertex_buffer(void* backend, mesh* mesh) {} + void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) {} -void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) {} -void uniform_f32(u32 program_id, const char* uniform_name, f32 value) {} -void uniform_i32(u32 program_id, const char* uniform_name, i32 value) {} -void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) {} + shader shader_create_separate(const char* vert_shader, const char* frag_shader) {} + void set_shader(shader s) {} -VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( - VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, - const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { - switch (severity) { - default: - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - ERROR("%s", callback_data->pMessage); - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - WARN("%s", callback_data->pMessage); - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - INFO("%s", callback_data->pMessage); - break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - TRACE("%s", callback_data->pMessage); - break; + void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) {} + void uniform_f32(u32 program_id, const char* uniform_name, f32 value) {} + void uniform_i32(u32 program_id, const char* uniform_name, i32 value) {} + void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) {} + + VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { + switch (severity) { + default: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + ERROR("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + WARN("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + INFO("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + TRACE("%s", callback_data->pMessage); + break; + } + return VK_FALSE; } - return VK_FALSE; -} #endif \ No newline at end of file diff --git a/src/std/containers/graphs.h b/src/std/containers/graphs.h new file mode 100644 index 0000000..47399e9 --- /dev/null +++ b/src/std/containers/graphs.h @@ -0,0 +1,15 @@ +/** + * @file graphs.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ + + +// Adjacency list backed graphs + +// Matrix backed graphs (not as useful) \ No newline at end of file diff --git a/src/std/containers/hashset.h b/src/std/containers/hashset.h new file mode 100644 index 0000000..f8e7073 --- /dev/null +++ b/src/std/containers/hashset.h @@ -0,0 +1,10 @@ +/** + * @file hashset.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ \ No newline at end of file diff --git a/src/std/containers/hashtable.h b/src/std/containers/hashtable.h new file mode 100644 index 0000000..c93dc19 --- /dev/null +++ b/src/std/containers/hashtable.h @@ -0,0 +1,10 @@ +/** + * @file hashtable.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ \ No newline at end of file diff --git a/src/systems/terrain.h b/src/systems/terrain.h index fa2d3b3..96875d9 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -8,3 +8,12 @@ * @copyright Copyright (c) 2024 * */ + +#include "defines.h" + +typedef struct terrain_state { + +} terrain_state; + +bool terrain_system_init(terrain_state* state); +void terrain_system_shutdown(terrain_state* state); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From fc35df8e999521b8be7c44800f4ff4665df3254a Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 27 Apr 2024 16:35:11 +1000 Subject: heightmap function signatures --- src/core.h | 2 +- src/logos/jobs.h | 4 ++-- src/maths/primitives.c | 16 +++----------- src/platform/mutex.c | 2 +- src/platform/mutex.h | 12 ++++++----- src/platform/thread.h | 6 +++--- src/renderer/cleanroom/backend_vulkan.h | 7 ++++--- src/renderer/cleanroom/ral.h | 12 +++++------ src/renderer/cleanroom/renderer.h | 2 +- src/renderer/cleanroom/types.h | 13 ++++++++---- src/renderer/render_types.h | 3 ++- src/std/containers/graphs.h | 7 +++---- src/std/containers/hashset.h | 6 +++--- src/std/containers/hashtable.h | 6 +++--- src/systems/physics.h | 2 +- src/systems/terrain.h | 37 ++++++++++++++++++++++++++++----- src/systems/text.h | 2 +- src/transform_hierarchy.h | 2 +- 18 files changed, 83 insertions(+), 58 deletions(-) (limited to 'src/systems/terrain.h') diff --git a/src/core.h b/src/core.h index dd5a695..be88c53 100644 --- a/src/core.h +++ b/src/core.h @@ -3,8 +3,8 @@ #include "defines.h" #include "input.h" #include "ral.h" -#include "terrain.h" #include "screenspace.h" +#include "terrain.h" #include "text.h" #include "threadpool.h" diff --git a/src/logos/jobs.h b/src/logos/jobs.h index cc2c8fa..ef4eed7 100644 --- a/src/logos/jobs.h +++ b/src/logos/jobs.h @@ -1,3 +1,3 @@ /** - * Common jobs that get run -*/ \ No newline at end of file + * Common jobs that get run + */ \ No newline at end of file diff --git a/src/maths/primitives.c b/src/maths/primitives.c index 42c51ea..55ff5fc 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -13,20 +13,10 @@ geometry_data geo_create_plane(f32x2 extents) { vertex_format format = VERTEX_STATIC_3D; vertex_darray* vertices = vertex_darray_new(4); - vertex_darray_push( - vertices, - (vertex) {.static_3d = { - .position = - }} - ); - - return (geometry_data) { - .format = format, - .vertices = - .has_indices = true, - } -} + vertex_darray_push(vertices, (vertex){ .static_3d = { .position = } }); + return (geometry_data) { .format = format, .vertices =.has_indices = true, } +} // OLD diff --git a/src/platform/mutex.c b/src/platform/mutex.c index 9735483..2aeb825 100644 --- a/src/platform/mutex.c +++ b/src/platform/mutex.c @@ -4,6 +4,6 @@ // TODO: implement in terms of pthreads #endif -#if defined (CEL_PLATFORM_WINDOWS) +#if defined(CEL_PLATFORM_WINDOWS) // TODO: implement using win32 api #endif \ No newline at end of file diff --git a/src/platform/mutex.h b/src/platform/mutex.h index 0552ea2..a0a4208 100644 --- a/src/platform/mutex.h +++ b/src/platform/mutex.h @@ -1,12 +1,12 @@ /** * @file mutex.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #include @@ -16,10 +16,12 @@ cel_mutex mutex_create(); void mutex_destroy(cel_mutex* mutex); -/** @brief Blocks until the mutex can be acquired. if returns false then an error occurred and can be checked (TODO) */ +/** @brief Blocks until the mutex can be acquired. if returns false then an error occurred and can + * be checked (TODO) */ bool mutex_lock(cel_mutex* mutex); -/** @brief Tries to acquire the mutex like `mutex_lock` but returns immediately if the mutex has already been locked */ +/** @brief Tries to acquire the mutex like `mutex_lock` but returns immediately if the mutex has + * already been locked */ bool mutex_try_lock(cel_mutex* mutex); /** @brief Releases a mutex. If it is already unlocked then does nothing */ diff --git a/src/platform/thread.h b/src/platform/thread.h index a3560cb..af07d3f 100644 --- a/src/platform/thread.h +++ b/src/platform/thread.h @@ -1,12 +1,12 @@ /** * @file thread.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ typedef struct cel_thread cel_thread; diff --git a/src/renderer/cleanroom/backend_vulkan.h b/src/renderer/cleanroom/backend_vulkan.h index 6798b13..c8d5777 100644 --- a/src/renderer/cleanroom/backend_vulkan.h +++ b/src/renderer/cleanroom/backend_vulkan.h @@ -3,7 +3,8 @@ #define GPU_SWAPCHAIN_IMG_COUNT 2 -typedef struct gpu_swapchain {} gpu_swapchain; +typedef struct gpu_swapchain { +} gpu_swapchain; typedef struct gpu_device { // In Vulkan we store both physical and logical device here VkPhysicalDevice physical_device; @@ -13,7 +14,8 @@ typedef struct gpu_device { VkPhysicalDeviceMemoryProperties memory; VkCommandPool pool; } gpu_device; -typedef struct gpu_pipeline {} gpu_pipeline; +typedef struct gpu_pipeline { +} gpu_pipeline; typedef struct gpu_renderpass { VkRenderPass vk_handle; @@ -21,7 +23,6 @@ typedef struct gpu_renderpass { u32 } gpu_renderpass; - typedef struct gpu_cmd_encoder { VkCommandBuffer cmd_buffer; } gpu_cmd_encoder; \ No newline at end of file diff --git a/src/renderer/cleanroom/ral.h b/src/renderer/cleanroom/ral.h index a1e9929..15eb027 100644 --- a/src/renderer/cleanroom/ral.h +++ b/src/renderer/cleanroom/ral.h @@ -5,9 +5,9 @@ * @details API that a graphics backend *must* implement * @version 0.1 * @date 2024-03-31 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once @@ -19,8 +19,8 @@ typedef struct gpu_swapchain gpu_swapchain; typedef struct gpu_device gpu_device; typedef struct gpu_pipeline gpu_pipeline; typedef struct gpu_renderpass gpu_renderpass; -typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission +typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording +typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission enum pipeline_kind { GRAPHICS, @@ -29,8 +29,8 @@ enum pipeline_kind { typedef struct shader_desc { const char* debug_name; - str8 filepath; // where it came from - str8 glsl; // contents + str8 filepath; // where it came from + str8 glsl; // contents } shader_desc; struct pipeline_desc { diff --git a/src/renderer/cleanroom/renderer.h b/src/renderer/cleanroom/renderer.h index 8012b49..ff342b0 100644 --- a/src/renderer/cleanroom/renderer.h +++ b/src/renderer/cleanroom/renderer.h @@ -1,7 +1,7 @@ #pragma once -#include "cleanroom/ral.h" #include "cleanroom/backend_vulkan.h" +#include "cleanroom/ral.h" typedef struct renderer2 { void* backend_state; diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h index 98c2e21..b18b5b8 100644 --- a/src/renderer/cleanroom/types.h +++ b/src/renderer/cleanroom/types.h @@ -10,7 +10,8 @@ CORE_DEFINE_HANDLE(sampler_handle); CORE_DEFINE_HANDLE(shader_handle); CORE_DEFINE_HANDLE(model_handle); -typedef struct transform_hierarchy {} transform_hierarchy; +typedef struct transform_hierarchy { +} transform_hierarchy; /** @brief Texture Description - used by texture creation functions */ typedef struct texture_desc { @@ -56,7 +57,12 @@ typedef struct model bp_material; // blinn-phong #include "maths_types.h" -typedef enum vertex_format { VERTEX_STATIC_3D, VERTEX_SPRITE, VERTEX_SKINNED, VERTEX_COUNT } vertex_format; +typedef enum vertex_format { + VERTEX_STATIC_3D, + VERTEX_SPRITE, + VERTEX_SKINNED, + VERTEX_COUNT +} vertex_format; typedef union vertex { struct { @@ -79,7 +85,7 @@ typedef union vertex { vec3 normal; vec4i bone_ids; // Integer vector for bone IDs vec4 bone_weights; // Weight of each bone's influence - } skinned_3d; /** @brief vertex format for skeletal (animated) geometry in 3D */ + } skinned_3d; /** @brief vertex format for skeletal (animated) geometry in 3D */ } vertex; KITC_DECL_TYPED_ARRAY(vertex) @@ -128,7 +134,6 @@ typedef struct model { /* ral.h */ - // command buffer gubbins /* --- Backends */ diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 387ac81..3bce88f 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -76,7 +76,8 @@ typedef struct texture { // bool is_loaded; // bool is_uploaded; // } blinn_phong_material; -// typedef blinn_phong_material material; // when we start using PBR, this will no longer be the case +// typedef blinn_phong_material material; // when we start using PBR, this will no longer be the +// case // // the default blinn-phong material. MUST be initialised with the function below // extern material DEFAULT_MATERIAL; diff --git a/src/std/containers/graphs.h b/src/std/containers/graphs.h index 47399e9..5dbec97 100644 --- a/src/std/containers/graphs.h +++ b/src/std/containers/graphs.h @@ -1,15 +1,14 @@ /** * @file graphs.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ - // Adjacency list backed graphs // Matrix backed graphs (not as useful) \ No newline at end of file diff --git a/src/std/containers/hashset.h b/src/std/containers/hashset.h index f8e7073..d153fd2 100644 --- a/src/std/containers/hashset.h +++ b/src/std/containers/hashset.h @@ -1,10 +1,10 @@ /** * @file hashset.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ \ No newline at end of file diff --git a/src/std/containers/hashtable.h b/src/std/containers/hashtable.h index c93dc19..f5d98e7 100644 --- a/src/std/containers/hashtable.h +++ b/src/std/containers/hashtable.h @@ -1,10 +1,10 @@ /** * @file hashtable.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ \ No newline at end of file diff --git a/src/systems/physics.h b/src/systems/physics.h index 5c96c6e..61d2008 100644 --- a/src/systems/physics.h +++ b/src/systems/physics.h @@ -15,7 +15,7 @@ enum collider_type { /** @brief generic collider structure */ typedef struct physics_collider { - u64 id; // ? Replace with handle? + u64 id; // ? Replace with handle? enum collider_type shape; transform transform; u8 layer; diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 96875d9..6558202 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -1,19 +1,46 @@ /** * @file terrain.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ +/* +Future: + - Chunked terrain + - Dynamic LOD +*/ + +#include "cleanroom/types.h" #include "defines.h" +#include "maths_types.h" +#include "mem.h" typedef struct terrain_state { - } terrain_state; +typedef struct heightmap { + u32x2 size; + void* image_data; +} heightmap; + bool terrain_system_init(terrain_state* state); -void terrain_system_shutdown(terrain_state* state); \ No newline at end of file +void terrain_system_shutdown(terrain_state* state); +void terrain_system_render_hmap(renderer* rend, terrain_state* state); + +heightmap heightmap_from_image(const char* filepath); +heightmap heightmap_from_perlin(/* TODO: perlin noise generation parameters */); + +/** @brief Get the height (the Y component) for a vertex at a particular coordinate in the heightmap + */ +f32 heightmap_height_at_xz(heightmap* hmap, f32 x, f32 z); + +/** @brief Calculate the normal vector of a vertex at a particular coordinate in the heightmap */ +vec3 heightmap_normal_at_xz(heightmap* hmap, f32 x, f32 z); + +/** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ +geometry_data geo_heightmap(arena* a, heightmap heightmap); \ No newline at end of file diff --git a/src/systems/text.h b/src/systems/text.h index 4fac0b8..dc396f0 100644 --- a/src/systems/text.h +++ b/src/systems/text.h @@ -8,8 +8,8 @@ #include "cleanroom/types.h" #include "darray.h" #include "defines.h" -#include "render_types.h" #include "ral.h" +#include "render_types.h" struct core; diff --git a/src/transform_hierarchy.h b/src/transform_hierarchy.h index d77b846..0921c19 100644 --- a/src/transform_hierarchy.h +++ b/src/transform_hierarchy.h @@ -4,8 +4,8 @@ #pragma once #include "maths_types.h" -#include "render_types.h" #include "ral.h" +#include "render_types.h" #define MAX_TF_NODE_CHILDREN \ 32 /** TEMP: Make it simpler to manage children in `transform_node`s */ -- cgit v1.2.3-70-g09d2 From 93c8d40b39fe55a626e66d412450fb4cca1f993b Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 27 Apr 2024 17:07:03 +1000 Subject: scene thoughts --- src/camera.h | 9 ++++++++- src/renderer/cleanroom/immediate.c | 18 ++++++++++++++++++ src/renderer/cleanroom/immediate.h | 20 ++++++++++++++++++++ src/renderer/cleanroom/simda.h | 18 ------------------ src/renderer/cleanroom/types.h | 3 +++ src/scene.h | 30 ++++++++++++++++++++++++++++++ src/systems/physics.h | 8 ++++++++ src/systems/terrain.h | 18 +++++++++++++----- 8 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 src/renderer/cleanroom/immediate.c create mode 100644 src/renderer/cleanroom/immediate.h delete mode 100644 src/renderer/cleanroom/simda.h create mode 100644 src/scene.h (limited to 'src/systems/terrain.h') diff --git a/src/camera.h b/src/camera.h index f7bc6eb..ec867c5 100644 --- a/src/camera.h +++ b/src/camera.h @@ -24,4 +24,11 @@ camera camera_create(vec3 pos, vec3 front, vec3 up, f32 fov); /** @brief get a 4x4 transform matrix for the view and perspective projection */ void camera_view_projection(camera *c, f32 screen_height, f32 screen_width, mat4 *out_view, - mat4 *out_proj); \ No newline at end of file + mat4 *out_proj); + +// TODO: Basic reusable camera controls +/* +Right click + move = pan +Left click = orbit camera +WASD = forward/backward/left/right +*/ \ No newline at end of file diff --git a/src/renderer/cleanroom/immediate.c b/src/renderer/cleanroom/immediate.c new file mode 100644 index 0000000..8e4bf7e --- /dev/null +++ b/src/renderer/cleanroom/immediate.c @@ -0,0 +1,18 @@ +#include "immediate.h" +#include "maths.h" +#include "primitives.h" +#include "render.h" +#include "types.h" + +void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour) { + // Create the vertices + geometry_data geometry = geo_create_uvsphere(radius, 16, 16); + geo_set_vertex_colours(&geometry, colour); + + // Upload to GPU + mat4 model = mat4_translation(pos); + + // Set pipeline + + // Draw +} \ No newline at end of file diff --git a/src/renderer/cleanroom/immediate.h b/src/renderer/cleanroom/immediate.h new file mode 100644 index 0000000..6d93c53 --- /dev/null +++ b/src/renderer/cleanroom/immediate.h @@ -0,0 +1,20 @@ +#pragma once + +#include "geometry.h" +#include "maths_types.h" + +// 3. SIMA (simplified immediate mode api) / render.h +// - dont need to worry about uploading mesh data +// - very useful for debugging +void imm_draw_cuboid(vec3 pos, quat rotation, f32x3 extents, vec4 colour); +void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour); +void imm_draw_camera_frustum(); + +// static void imm_draw_model( +// const char* model_filepath); // tracks internally whether the model is loaded + +// static void imm_draw_model(const char* model_filepath) { + // check that model is loaded + // if not loaded, load model and upload to gpu - LRU cache for models + // else submit draw call +// } \ No newline at end of file diff --git a/src/renderer/cleanroom/simda.h b/src/renderer/cleanroom/simda.h deleted file mode 100644 index d0b4794..0000000 --- a/src/renderer/cleanroom/simda.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "maths_types.h" - -// 3. SIMA (simplified immediate mode api) / render.h -// - dont need to worry about uploading mesh data -// - very useful for debugging -void imm_draw_cuboid(); -void imm_draw_sphere(vec3 pos, f32 radius, vec4 colour); -void imm_draw_camera_frustum(); -static void imm_draw_model( - const char* model_filepath); // tracks internally whether the model is loaded - -static void imm_draw_model(const char* model_filepath) { - // check that model is loaded - // if not loaded, load model and upload to gpu - LRU cache for models - // else submit draw call -} \ No newline at end of file diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h index b18b5b8..7a6cfbd 100644 --- a/src/renderer/cleanroom/types.h +++ b/src/renderer/cleanroom/types.h @@ -96,8 +96,11 @@ typedef struct geometry_data { vertex_darray vertices; bool has_indices; u32_darray indices; + vec3 colour; /** Optional: set vertex colours */ } geometry_data; +void geo_set_vertex_colours(geometry_data* geo, vec4 colour); + typedef struct mesh { buffer_handle vertex_buffer; buffer_handle index_buffer; diff --git a/src/scene.h b/src/scene.h new file mode 100644 index 0000000..2cc4d8a --- /dev/null +++ b/src/scene.h @@ -0,0 +1,30 @@ +/** + * @file scene.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-04-27 + * + * @copyright Copyright (c) 2024 + * + */ +#include "defines.h" +#include "types.h" + +typedef struct scene { + // directional_light dir_light; + // point_light point_lights[4]; + // size_t n_point_lights; +} scene; + +bool scene_add_directional_light(scene* s /* TODO */); +bool scene_add_point_light(scene* s /* TODO */); + +// There can only be one heightmap terrain at a time right now. +bool scene_add_heightmap(scene* s /* TODO */); +bool scene_delete_heightmap(scene* s); + +bool scene_add_model(scene *s, model_handle model); +void scene_remove_model(scene *s, model_handle model); + +// TODO: functions to load and save scenes from disk \ No newline at end of file diff --git a/src/systems/physics.h b/src/systems/physics.h index 61d2008..7239ab5 100644 --- a/src/systems/physics.h +++ b/src/systems/physics.h @@ -1,5 +1,6 @@ #pragma once +#include "geometry.h" #include "maths_types.h" // 'system' means that it gets called per frame @@ -17,11 +18,18 @@ enum collider_type { typedef struct physics_collider { u64 id; // ? Replace with handle? enum collider_type shape; + union collider_data { + cuboid cuboid; + sphere sphere; + } geometry; transform transform; u8 layer; bool on_ground; } physics_collider; +// What else do I need? +// intersection methods + typedef struct physics_world { physics_settings settings; } physics_world; diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 6558202..3d6f1c1 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -20,19 +20,23 @@ Future: #include "maths_types.h" #include "mem.h" -typedef struct terrain_state { -} terrain_state; - typedef struct heightmap { + str8 filepath; u32x2 size; void* image_data; + bool is_uploaded; } heightmap; +typedef struct terrain_state { + arena terrain_allocator; + heightmap* heightmap; // NULL = no heightmap +} terrain_state; + bool terrain_system_init(terrain_state* state); void terrain_system_shutdown(terrain_state* state); void terrain_system_render_hmap(renderer* rend, terrain_state* state); -heightmap heightmap_from_image(const char* filepath); +heightmap heightmap_from_image(str8 filepath); heightmap heightmap_from_perlin(/* TODO: perlin noise generation parameters */); /** @brief Get the height (the Y component) for a vertex at a particular coordinate in the heightmap @@ -43,4 +47,8 @@ f32 heightmap_height_at_xz(heightmap* hmap, f32 x, f32 z); vec3 heightmap_normal_at_xz(heightmap* hmap, f32 x, f32 z); /** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ -geometry_data geo_heightmap(arena* a, heightmap heightmap); \ No newline at end of file +geometry_data geo_heightmap(arena* a, heightmap heightmap); + +// somewhere there will be an easy way to add a heightmap + +// scene_add_heightmap \ No newline at end of file -- cgit v1.2.3-70-g09d2 From aed7d1b7ac340c19656059c9cbd94aff40952f83 Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Fri, 3 May 2024 21:37:51 +1000 Subject: create logical device --- src/defines.h | 4 +- src/renderer/backends/backend_dx11.h | 1 - src/renderer/backends/backend_vulkan.c | 237 +++++++++++++++++++++++++++++---- src/renderer/backends/vulkan_helpers.h | 42 +++++- src/renderer/bind_group_layouts.h | 4 +- src/renderer/cleanroom/types.h | 2 +- src/renderer/immediate.h | 6 +- src/renderer/ral.h | 7 +- src/renderer/ral_types.h | 14 +- src/renderer/render.h | 2 +- src/renderer/render_types.h | 16 +-- src/renderer/renderpasses.h | 7 +- src/scene.h | 10 +- src/std/buf.h | 6 +- src/std/mem.c | 9 +- src/std/mem.h | 7 + src/systems/terrain.h | 2 +- xmake.lua | 2 +- 18 files changed, 299 insertions(+), 79 deletions(-) (limited to 'src/systems/terrain.h') diff --git a/src/defines.h b/src/defines.h index ec526e0..4b6f8c7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -66,8 +66,8 @@ Renderer backend defines: // Platform will inform renderer backend (unless user overrides) #if defined(CEL_PLATFORM_LINUX) -#define CEL_REND_BACKEND_OPENGL 1 -// #define CEL_REND_BACKEND_VULKAN 1 +// #define CEL_REND_BACKEND_OPENGL 1 +#define CEL_REND_BACKEND_VULKAN 1 #endif #if defined(CEL_PLATFORM_WINDOWS) diff --git a/src/renderer/backends/backend_dx11.h b/src/renderer/backends/backend_dx11.h index 8e3a513..53738aa 100644 --- a/src/renderer/backends/backend_dx11.h +++ b/src/renderer/backends/backend_dx11.h @@ -8,7 +8,6 @@ // typedef struct gpu_swapchain gpu_swapchain; typedef struct gpu_device { - // VkPhysicalDevice physical_device; // VkDevice logical_device; // VkPhysicalDeviceProperties properties; diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index ae857a0..c21a6b9 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -5,6 +5,7 @@ #include #include "backend_vulkan.h" +#include "maths_types.h" #include "mem.h" #include "vulkan_helpers.h" @@ -31,6 +32,8 @@ typedef struct vulkan_context { u32 screen_width; u32 screen_height; + + VkDebugUtilsMessengerEXT vk_debugger; } vulkan_context; static vulkan_context context; @@ -39,6 +42,13 @@ static vulkan_context context; /** @brief Enumerates and selects the most appropriate graphics device */ bool select_physical_device(gpu_device* out_device); + +bool is_physical_device_suitable(VkPhysicalDevice device); + +queue_family_indices find_queue_families(VkPhysicalDevice device); + +bool create_logical_device(gpu_device* out_device); + /** @brief Helper function for creating array of all extensions we want */ cstr_darray* get_all_extensions(); @@ -49,7 +59,7 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { // Create an allocator size_t temp_arena_size = 1024 * 1024; - arena_create(malloc(temp_arena_size), temp_arena_size); + context.temp_arena = arena_create(malloc(temp_arena_size), temp_arena_size); // Setup Vulkan instance VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; @@ -63,20 +73,61 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { create_info.pApplicationInfo = &app_info; // Extensions - // FIXME: Use my own extension choices - // cstr_darray* required_extensions = cstr_darray_new(2); + cstr_darray* required_extensions = cstr_darray_new(2); // cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); - // create_info.enabledExtensionCount = cstr_darray_len(required_extensions); - // create_info.ppEnabledExtensionNames = required_extensions->data; + uint32_t count; const char** extensions = glfwGetRequiredInstanceExtensions(&count); - create_info.enabledExtensionCount = count; - create_info.ppEnabledExtensionNames = extensions; + for (u32 i = 0; i < count; i++) { + cstr_darray_push(required_extensions, extensions[i]); + } + + cstr_darray_push(required_extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + + DEBUG("Required extensions:"); + for (u32 i = 0; i < cstr_darray_len(required_extensions); i++) { + DEBUG(" %s", required_extensions->data[i]); + } + + create_info.enabledExtensionCount = cstr_darray_len(required_extensions); + create_info.ppEnabledExtensionNames = required_extensions->data; // TODO: Validation layers create_info.enabledLayerCount = 0; create_info.ppEnabledLayerNames = NULL; + INFO("Validation layers enabled"); + cstr_darray* desired_validation_layers = cstr_darray_new(1); + cstr_darray_push(desired_validation_layers, "VK_LAYER_KHRONOS_validation"); + + u32 n_available_layers = 0; + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, 0)); + TRACE("%d available layers", n_available_layers); + VkLayerProperties* available_layers = + arena_alloc(&context.temp_arena, n_available_layers * sizeof(VkLayerProperties)); + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, available_layers)); + + for (int i = 0; i < cstr_darray_len(desired_validation_layers); i++) { + // look through layers to make sure we can find the ones we want + bool found = false; + for (int j = 0; j < n_available_layers; j++) { + if (str8_equals(str8_cstr_view(desired_validation_layers->data[i]), + str8_cstr_view(available_layers[j].layerName))) { + found = true; + TRACE("Found layer %s", desired_validation_layers->data[i]); + break; + } + } + + if (!found) { + FATAL("Required validation is missing %s", desired_validation_layers->data[i]); + return false; + } + } + INFO("All validation layers are present"); + create_info.enabledLayerCount = cstr_darray_len(desired_validation_layers); + create_info.ppEnabledLayerNames = desired_validation_layers->data; + VkResult result = vkCreateInstance(&create_info, NULL, &context.instance); if (result != VK_SUCCESS) { ERROR("vkCreateInstance failed with result: %u", result); @@ -84,6 +135,25 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { } TRACE("Vulkan Instance created"); + DEBUG("Creating Vulkan debugger"); + u32 log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT + }; + debug_create_info.messageSeverity = log_severity; + debug_create_info.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; + debug_create_info.pfnUserCallback = vk_debug_callback; + + PFN_vkCreateDebugUtilsMessengerEXT func = + (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance, + "vkCreateDebugUtilsMessengerEXT"); + assert(func); + VK_CHECK(func(context.instance, &debug_create_info, context.allocator, &context.vk_debugger)); + DEBUG("Vulkan Debugger created"); + // Surface creation VkSurfaceKHR surface; VK_CHECK(glfwCreateWindowSurface(context.instance, window, NULL, &surface)); @@ -96,39 +166,43 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { void gpu_backend_shutdown() { arena_free_storage(&context.temp_arena); } bool gpu_device_create(gpu_device* out_device) { + // First things first store this poitner from the renderer + context.device = out_device; + + arena_save savept = arena_savepoint(&context.temp_arena); // Physical device if (!select_physical_device(out_device)) { return false; } TRACE("Physical device selected"); - // Features - VkPhysicalDeviceFeatures device_features = { 0 }; - device_features.samplerAnisotropy = VK_TRUE; // request anistrophy - // Logical device - VkDeviceQueueCreateInfo queue_create_info[2]; - //.. - VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; - device_create_info.queueCreateInfoCount = VULKAN_QUEUES_COUNT; - device_create_info.pQueueCreateInfos = queue_create_info; - device_create_info.pEnabledFeatures = &device_features; - device_create_info.enabledExtensionCount = 1; - const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; - device_create_info.ppEnabledExtensionNames = &extension_names; - - VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info, - context.allocator, &out_device->logical_device); - if (result != VK_SUCCESS) { - FATAL("Error creating logical device with status %u\n", result); - exit(1); - } - TRACE("Logical device created"); + create_logical_device(out_device); + // VkDeviceQueueCreateInfo queue_create_info = {}; + + // queue_family_indices indices = find_queue_families(context.device->physical_device); + // //.. + // VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + // device_create_info.queueCreateInfoCount = VULKAN_QUEUES_COUNT; + // device_create_info.pQueueCreateInfos = queue_create_info; + // device_create_info.pEnabledFeatures = &device_features; + // device_create_info.enabledExtensionCount = 1; + // const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; + // device_create_info.ppEnabledExtensionNames = &extension_names; + + // VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info, + // context.allocator, &out_device->logical_device); + // if (result != VK_SUCCESS) { + // FATAL("Error creating logical device with status %u\n", result); + // exit(1); + // } + // TRACE("Logical device created"); // Queues // Create the command pool + arena_rewind(savept); // Free any temp data return true; } @@ -316,4 +390,109 @@ inline void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) { vkCmdDrawIndexed(encoder->cmd_buffer, index_count, 1, 0, 0, 0); } -bool select_physical_device(gpu_device* out_device) {} \ No newline at end of file +bool select_physical_device(gpu_device* out_device) { + u32 physical_device_count = 0; + VK_CHECK(vkEnumeratePhysicalDevices(context.instance, &physical_device_count, 0)); + if (physical_device_count == 0) { + FATAL("No devices that support vulkan were found"); + return false; + } + TRACE("Number of devices found %d", physical_device_count); + + VkPhysicalDevice* physical_devices = + arena_alloc(&context.temp_arena, physical_device_count * sizeof(VkPhysicalDevice)); + VK_CHECK(vkEnumeratePhysicalDevices(context.instance, &physical_device_count, physical_devices)); + + bool found = false; + for (u32 device_i = 0; device_i < physical_device_count; device_i++) { + if (is_physical_device_suitable(physical_devices[device_i])) { + out_device->physical_device = physical_devices[device_i]; + found = true; + break; + } + } + + if (!found) { + FATAL("Couldn't find a suitable physical device"); + return false; + } + + return true; +} + +bool is_physical_device_suitable(VkPhysicalDevice device) { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(device, &properties); + + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(device, &features); + + VkPhysicalDeviceMemoryProperties memory; + vkGetPhysicalDeviceMemoryProperties(device, &memory); + + // TODO: Check against these device properties + + queue_family_indices indices = find_queue_families(device); + + return indices.has_graphics; +} + +queue_family_indices find_queue_families(VkPhysicalDevice device) { + queue_family_indices indices = { 0 }; + + u32 queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, 0); + + VkQueueFamilyProperties* queue_families = + arena_alloc(&context.temp_arena, queue_family_count * sizeof(VkQueueFamilyProperties)); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families); + + for (u32 queue_i = 0; queue_i < queue_family_count; queue_i++) { + // Graphics queue + if (queue_families[queue_i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphics_queue_index = queue_i; + indices.has_graphics = true; + } + } + + return indices; +} + +bool create_logical_device(gpu_device* out_device) { + queue_family_indices indices = find_queue_families(out_device->physical_device); + + f32 prio_one = 1.0; + VkDeviceQueueCreateInfo queue_create_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + queue_create_info.queueFamilyIndex = indices.graphics_queue_index; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &prio_one; + queue_create_info.flags = 0; + queue_create_info.pNext = 0; + + // Features + VkPhysicalDeviceFeatures device_features = { 0 }; + device_features.samplerAnisotropy = VK_TRUE; // request anistrophy + + // Device itself + VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &queue_create_info; + device_create_info.pEnabledFeatures = &device_features; + device_create_info.enabledExtensionCount = 1; + const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; + device_create_info.ppEnabledExtensionNames = &extension_names; + + // deprecated + device_create_info.enabledLayerCount = 0; + device_create_info.ppEnabledLayerNames = 0; + + VkResult result = vkCreateDevice(context.device->physical_device, &device_create_info, + context.allocator, &context.device->logical_device); + if (result != VK_SUCCESS) { + printf("error creating logical device with status %u\n", result); + ERROR_EXIT("Unable to create vulkan logical device. Exiting.."); + } + TRACE("Logical device created"); + + return true; +} \ No newline at end of file diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h index 4bd02f1..baff4e7 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/renderer/backends/vulkan_helpers.h @@ -20,16 +20,27 @@ static void plat_get_required_extension_names(cstr_darray* extensions) { } // TODO(omni): port to using internal assert functions -#define VK_CHECK(vulkan_expr) \ - do { \ - VkResult res = vulkan_expr; \ - if (res != VK_SUCCESS) { \ +#define VK_CHECK(vulkan_expr) \ + do { \ + VkResult res = vulkan_expr; \ + if (res != VK_SUCCESS) { \ ERROR_EXIT("Vulkan error: %u", res); \ - } \ + } \ } while (0) // TODO: typedef struct vk_debugger {} vk_debugger; +typedef struct queue_family_indices { + u32 graphics_queue_index; + u32 present_queue_index; + u32 compute_queue_index; + u32 transfer_queue_index; + bool has_graphics; + bool has_present; + bool has_compute; + bool has_transfer; +} queue_family_indices; + typedef struct vulkan_physical_device_requirements { bool graphics; bool present; @@ -168,4 +179,25 @@ static bool physical_device_meets_requirements( } return false; +} + +VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { + switch (severity) { + default: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + ERROR("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + WARN("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + INFO("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + TRACE("%s", callback_data->pMessage); + break; + } + return VK_FALSE; } \ No newline at end of file diff --git a/src/renderer/bind_group_layouts.h b/src/renderer/bind_group_layouts.h index d163fab..d2571ef 100644 --- a/src/renderer/bind_group_layouts.h +++ b/src/renderer/bind_group_layouts.h @@ -4,9 +4,9 @@ * @brief Common bindgroups (descriptor set layouts) * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "defines.h" diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h index 7360ebe..6686be5 100644 --- a/src/renderer/cleanroom/types.h +++ b/src/renderer/cleanroom/types.h @@ -2,5 +2,5 @@ #include "darray.h" #include "defines.h" #include "maths_types.h" -#include "str.h" #include "render_types.h" +#include "str.h" diff --git a/src/renderer/immediate.h b/src/renderer/immediate.h index 6d93c53..b9d7c61 100644 --- a/src/renderer/immediate.h +++ b/src/renderer/immediate.h @@ -14,7 +14,7 @@ void imm_draw_camera_frustum(); // const char* model_filepath); // tracks internally whether the model is loaded // static void imm_draw_model(const char* model_filepath) { - // check that model is loaded - // if not loaded, load model and upload to gpu - LRU cache for models - // else submit draw call +// check that model is loaded +// if not loaded, load model and upload to gpu - LRU cache for models +// else submit draw call // } \ No newline at end of file diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 8e49dbe..7c143f2 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -11,10 +11,10 @@ */ #pragma once -#include "ral_types.h" +#include "buf.h" #include "defines.h" +#include "ral_types.h" #include "str.h" -#include "buf.h" // Unrelated forward declares typedef struct arena arena; @@ -60,7 +60,6 @@ struct graphics_pipeline_desc { }; typedef struct gpu_renderpass_desc { - } gpu_renderpass_desc; // --- Lifecycle functions @@ -97,7 +96,7 @@ void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline); void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -void encode_set_bind_group(); // TODO +void encode_set_bind_group(); // TODO void encode_draw(gpu_cmd_encoder* encoder); void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index d6c5865..ae54b53 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -1,18 +1,18 @@ /** * @file ral_types.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once +#include "darray.h" #include "defines.h" #include "maths_types.h" -#include "darray.h" #ifndef RENDERER_TYPED_HANDLES CORE_DEFINE_HANDLE(buffer_handle); @@ -99,11 +99,7 @@ KITC_DECL_TYPED_ARRAY(u32) #define TYPED_VERTEX_ARRAY #endif -typedef enum gpu_cull_mode { - CULL_BACK_FACE, - CULL_FRONT_FACE, - CULL_COUNT -} gpu_cull_mode; +typedef enum gpu_cull_mode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } gpu_cull_mode; // ? How to tie together materials and shaders diff --git a/src/renderer/render.h b/src/renderer/render.h index a9370e0..e6dd8b8 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -10,8 +10,8 @@ */ #pragma once -#include "render_types.h" #include "ral_types.h" +#include "render_types.h" bool renderer_init(renderer* ren); void renderer_shutdown(renderer* ren); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 4866ef4..a5c0c1a 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -1,21 +1,21 @@ /** * @file render_types.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once -#include "ral_types.h" #include "ral.h" +#include "ral_types.h" #if defined(CEL_PLATFORM_WINDOWS) // #include "backend_dx11.h" -#include "backend_vulkan.h" #endif +#include "backend_vulkan.h" struct GLFWwindow; @@ -37,7 +37,7 @@ typedef struct renderer { typedef struct geometry_data { vertex_format format; - vertex_darray* vertices; // TODO: make it not a pointer + vertex_darray* vertices; // TODO: make it not a pointer bool has_indices; u32_darray indices; vec3 colour; /** Optional: set vertex colours */ @@ -66,8 +66,8 @@ typedef struct model { typedef struct texture { u32 texture_id; char name[256]; - void *image_data; - void *backend_data; + void* image_data; + void* backend_data; u32 width; u32 height; u8 channel_count; diff --git a/src/renderer/renderpasses.h b/src/renderer/renderpasses.h index 67badaa..91970d8 100644 --- a/src/renderer/renderpasses.h +++ b/src/renderer/renderpasses.h @@ -4,9 +4,9 @@ * @brief Built-in renderpasses to the engine * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "maths_types.h" @@ -25,7 +25,8 @@ typedef struct render_entity { // Don't need to pass in *anything*. gpu_renderpass* renderpass_blinn_phong_create(); -void renderpass_blinn_phong_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); +void renderpass_blinn_phong_execute(gpu_renderpass* pass, render_entity* entities, + size_t entity_count); gpu_renderpass* renderpass_shadows_create(); void renderpass_shadows_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); \ No newline at end of file diff --git a/src/scene.h b/src/scene.h index 2cc4d8a..6cac061 100644 --- a/src/scene.h +++ b/src/scene.h @@ -1,12 +1,12 @@ /** * @file scene.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #include "defines.h" #include "types.h" @@ -24,7 +24,7 @@ bool scene_add_point_light(scene* s /* TODO */); bool scene_add_heightmap(scene* s /* TODO */); bool scene_delete_heightmap(scene* s); -bool scene_add_model(scene *s, model_handle model); -void scene_remove_model(scene *s, model_handle model); +bool scene_add_model(scene* s, model_handle model); +void scene_remove_model(scene* s, model_handle model); // TODO: functions to load and save scenes from disk \ No newline at end of file diff --git a/src/std/buf.h b/src/std/buf.h index b0f8b85..de093ec 100644 --- a/src/std/buf.h +++ b/src/std/buf.h @@ -1,12 +1,12 @@ /** * @file buf.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "defines.h" diff --git a/src/std/mem.c b/src/std/mem.c index 5468898..4886d72 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -31,4 +31,11 @@ void arena_free_all(arena* a) { a->curr = a->begin; // pop everything at once and reset to the start. } -void arena_free_storage(arena* a) { free(a->begin); } \ No newline at end of file +void arena_free_storage(arena* a) { free(a->begin); } + +arena_save arena_savepoint(arena* a) { + arena_save savept = { .arena = a, .savepoint = a->curr }; + return savept; +} + +void arena_rewind(arena_save savepoint) { savepoint.arena->curr = savepoint.savepoint; } \ No newline at end of file diff --git a/src/std/mem.h b/src/std/mem.h index 2f92894..bbfb852 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -18,9 +18,16 @@ typedef struct arena { char* end; } arena; +typedef struct arena_save { + arena* arena; + char* savepoint; +} arena_save; + arena arena_create(void* backing_buffer, size_t capacity); void* arena_alloc(arena* a, size_t size); void* arena_alloc_align(arena* a, size_t size, size_t align); void arena_free_all(arena* a); void arena_free_storage(arena* a); +arena_save arena_savepoint(arena* a); +void arena_rewind(arena_save savepoint); // TODO: arena_resize \ No newline at end of file diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 3d6f1c1..a8bff17 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -29,7 +29,7 @@ typedef struct heightmap { typedef struct terrain_state { arena terrain_allocator; - heightmap* heightmap; // NULL = no heightmap + heightmap* heightmap; // NULL = no heightmap } terrain_state; bool terrain_system_init(terrain_state* state); diff --git a/xmake.lua b/xmake.lua index ab6a7a6..949dd76 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,6 +1,6 @@ set_project("celeritas") set_version("0.1.0") -set_config("cc", "clang-cl") +set_config("cc", "gcc") add_rules("mode.debug", "mode.release") -- we have two modes: debug & release -- cgit v1.2.3-70-g09d2 From 8c714a082e4b8069b6f1c29e83e09f406f1c965a Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 4 May 2024 11:15:49 +1000 Subject: delete cleanroom --- src/renderer/cleanroom/README.md | 1 - src/renderer/cleanroom/renderer.c | 4 ---- src/renderer/cleanroom/renderer.h | 14 -------------- src/renderer/cleanroom/types.h | 6 ------ src/systems/terrain.h | 3 ++- 5 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 src/renderer/cleanroom/README.md delete mode 100644 src/renderer/cleanroom/renderer.c delete mode 100644 src/renderer/cleanroom/renderer.h delete mode 100644 src/renderer/cleanroom/types.h (limited to 'src/systems/terrain.h') diff --git a/src/renderer/cleanroom/README.md b/src/renderer/cleanroom/README.md deleted file mode 100644 index d510f16..0000000 --- a/src/renderer/cleanroom/README.md +++ /dev/null @@ -1 +0,0 @@ -# Cleanroom / Re-jig of the renderer structure \ No newline at end of file diff --git a/src/renderer/cleanroom/renderer.c b/src/renderer/cleanroom/renderer.c deleted file mode 100644 index a874664..0000000 --- a/src/renderer/cleanroom/renderer.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "defines.h" -#include "render_types.h" - -bool renderer_init() {} \ No newline at end of file diff --git a/src/renderer/cleanroom/renderer.h b/src/renderer/cleanroom/renderer.h deleted file mode 100644 index ff342b0..0000000 --- a/src/renderer/cleanroom/renderer.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "cleanroom/backend_vulkan.h" -#include "cleanroom/ral.h" - -typedef struct renderer2 { - void* backend_state; - gpu_device* device; - gpu_pipeline* static_opaque_pipeline; -} renderer2; - -// mesh -// model -// material \ No newline at end of file diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h deleted file mode 100644 index 6686be5..0000000 --- a/src/renderer/cleanroom/types.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "darray.h" -#include "defines.h" -#include "maths_types.h" -#include "render_types.h" -#include "str.h" diff --git a/src/systems/terrain.h b/src/systems/terrain.h index a8bff17..745ca22 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -15,10 +15,11 @@ Future: - Dynamic LOD */ -#include "cleanroom/types.h" #include "defines.h" #include "maths_types.h" #include "mem.h" +#include "str.h" +#include "render_types.h" typedef struct heightmap { str8 filepath; -- cgit v1.2.3-70-g09d2 From a51ef12d8583522ee229a0195a4132652f0f9cd8 Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 4 May 2024 15:47:54 +1000 Subject: finish swapchain creation --- assets/shaders/triangle.frag | 0 assets/shaders/triangle.vert | 0 src/renderer/backends/backend_vulkan.c | 74 +++++++++++++++++----------------- src/renderer/backends/backend_vulkan.h | 6 +++ src/renderer/backends/vulkan_helpers.h | 19 ++++++++- src/renderer/ral.h | 2 +- src/std/utils.h | 4 ++ src/systems/terrain.h | 2 +- 8 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 assets/shaders/triangle.frag create mode 100644 assets/shaders/triangle.vert create mode 100644 src/std/utils.h (limited to 'src/systems/terrain.h') diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag new file mode 100644 index 0000000..e69de29 diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert new file mode 100644 index 0000000..e69de29 diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 08e62bf..028cde8 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -13,7 +13,7 @@ #include "defines.h" #include "log.h" #include "ral.h" -#include "ral_types.h" +#include "utils.h" // TEMP #define SCREEN_WIDTH 1000 @@ -182,32 +182,8 @@ bool gpu_device_create(gpu_device* out_device) { } TRACE("Physical device selected"); - // vulkan_device_query_swapchain_support(out_device->physical_device, context.surface, - // &context.swapchain_support); - - // Logical device + // Logical device & Queues create_logical_device(out_device); - // VkDeviceQueueCreateInfo queue_create_info = {}; - - // queue_family_indices indices = find_queue_families(context.device->physical_device); - // //.. - // VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; - // device_create_info.queueCreateInfoCount = VULKAN_QUEUES_COUNT; - // device_create_info.pQueueCreateInfos = queue_create_info; - // device_create_info.pEnabledFeatures = &device_features; - // device_create_info.enabledExtensionCount = 1; - // const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; - // device_create_info.ppEnabledExtensionNames = &extension_names; - - // VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info, - // context.allocator, &out_device->logical_device); - // if (result != VK_SUCCESS) { - // FATAL("Error creating logical device with status %u\n", result); - // exit(1); - // } - // TRACE("Logical device created"); - - // Queues // Create the command pool @@ -216,29 +192,55 @@ bool gpu_device_create(gpu_device* out_device) { } bool gpu_swapchain_create(gpu_swapchain* out_swapchain) { - VkExtent2D swapchain_extent = { context.screen_width, context.screen_height }; + out_swapchain->swapchain_arena = arena_create(malloc(1024), 1024); + vulkan_swapchain_support_info swapchain_support = context.swapchain_support; - // find a format + // TODO: custom swapchain extents VkExtent2D swapchain_extent = { width, height }; + VkSurfaceFormatKHR image_format = choose_swapchain_format(&swapchain_support); + out_swapchain->image_format = image_format; VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; // guaranteed to be implemented + out_swapchain->present_mode = present_mode; + + u32 image_count = swapchain_support.capabilities.minImageCount + 1; + out_swapchain->image_count = image_count; VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR }; swapchain_create_info.surface = context.surface; - swapchain_create_info.minImageCount = 2; - // TODO: image_ fields + swapchain_create_info.minImageCount = image_count; + swapchain_create_info.imageFormat = image_format.format; + swapchain_create_info.imageColorSpace = image_format.colorSpace; + swapchain_create_info.imageExtent = swapchain_support.capabilities.currentExtent; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchain_create_info.queueFamilyIndexCount = 0; - swapchain_create_info.pQueueFamilyIndices = 0; + swapchain_create_info.pQueueFamilyIndices = NULL; - // TODO: preTransform + swapchain_create_info.preTransform = swapchain_support.capabilities.currentTransform; swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchain_create_info.presentMode = present_mode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = 0; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + out_swapchain->extent = swapchain_support.capabilities.currentExtent; VK_CHECK(vkCreateSwapchainKHR(context.device->logical_device, &swapchain_create_info, context.allocator, &out_swapchain->handle)); TRACE("Vulkan Swapchain created"); + + // Retrieve Images + out_swapchain->images = + arena_alloc(&out_swapchain->swapchain_arena, image_count * sizeof(VkImage)); + VK_CHECK(vkGetSwapchainImagesKHR(context.device->logical_device, out_swapchain->handle, + &image_count, out_swapchain->images)); + + return true; +} + +void gpu_swapchain_destroy(gpu_swapchain* swapchain) { + arena_free_storage(&swapchain->swapchain_arena); + vkDestroySwapchainKHR(context.device, swapchain->handle, context.allocator); } gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { @@ -482,7 +484,7 @@ queue_family_indices find_queue_families(VkPhysicalDevice device) { VkBool32 present_support = false; vkGetPhysicalDeviceSurfaceSupportKHR(device, q_fam_i, context.surface, &present_support); - if (present_support) { + if (present_support && !indices.has_present) { indices.present_family_index = q_fam_i; indices.has_present = true; } @@ -491,8 +493,6 @@ queue_family_indices find_queue_families(VkPhysicalDevice device) { return indices; } -const char* bool_str(bool input) { return input ? "True" : "False"; } - bool create_logical_device(gpu_device* out_device) { queue_family_indices indices = find_queue_families(out_device->physical_device); INFO(" %s | %s | %s | %s | %s", bool_str(indices.has_graphics), bool_str(indices.has_present), diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 8c6b772..0114d7a 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -28,6 +28,12 @@ typedef struct queue_family_indices { typedef struct gpu_swapchain { VkSwapchainKHR handle; + arena swapchain_arena; + VkExtent2D extent; + VkSurfaceFormatKHR image_format; + VkPresentModeKHR present_mode; + VkImage* images; + u32 image_count; } gpu_swapchain; typedef struct gpu_device { diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h index 03ee814..55d8846 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/renderer/backends/vulkan_helpers.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -54,8 +55,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data); -void vulkan_device_query_swapchain_support(VkPhysicalDevice device, VkSurfaceKHR surface, - vulkan_swapchain_support_info* out_support_info) { +static void vulkan_device_query_swapchain_support(VkPhysicalDevice device, VkSurfaceKHR surface, + vulkan_swapchain_support_info* out_support_info) { // TODO: add VK_CHECK to these calls! // Surface capabilities @@ -78,6 +79,20 @@ void vulkan_device_query_swapchain_support(VkPhysicalDevice device, VkSurfaceKHR } } +static VkSurfaceFormatKHR choose_swapchain_format( + vulkan_swapchain_support_info* swapchain_support) { + assert(swapchain_support->format_count > 0); + // find a format + for (u32 i = 0; i < swapchain_support->format_count; i++) { + VkSurfaceFormatKHR format = swapchain_support->formats[i]; + if (format.format == VK_FORMAT_B8G8R8A8_SRGB && + format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + return format; + } + } + return swapchain_support->formats[0]; +} + // static bool physical_device_meets_requirements( // VkPhysicalDevice device, VkSurfaceKHR surface, const VkPhysicalDeviceProperties* properties, // const VkPhysicalDeviceFeatures* features, diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 7c143f2..f202e51 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -77,7 +77,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip void gpu_pipeline_destroy(gpu_pipeline* pipeline); bool gpu_swapchain_create(gpu_swapchain* out_swapchain); -void gpu_swapchain_destroy(); +void gpu_swapchain_destroy(gpu_swapchain* swapchain); void gpu_cmd_encoder_begin(); void gpu_cmd_encoder_begin_render(); diff --git a/src/std/utils.h b/src/std/utils.h new file mode 100644 index 0000000..c9827a3 --- /dev/null +++ b/src/std/utils.h @@ -0,0 +1,4 @@ +#pragma once +#include + +const char* bool_str(bool input) { return input ? "True" : "False"; } \ No newline at end of file diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 745ca22..bfd90b5 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -18,8 +18,8 @@ Future: #include "defines.h" #include "maths_types.h" #include "mem.h" -#include "str.h" #include "render_types.h" +#include "str.h" typedef struct heightmap { str8 filepath; -- cgit v1.2.3-70-g09d2