diff --git a/tests/basic/src/main.cpp b/tests/basic/src/main.cpp index f801320..660e362 100644 --- a/tests/basic/src/main.cpp +++ b/tests/basic/src/main.cpp @@ -1,13 +1,168 @@ -#include "basalt_context.h" -#include "basalt_window.h" +#include "vulkan/basalt_command_buffer.h" +#include "vulkan/basalt_swapchain.h" -int main() +void application() { - basalt::Window window(640, 480, "Hello Vulkan!"); + basalt::Context ctx("Basic", + basalt::darray({ + "VK_LAYER_KHRONOS_validation" + }, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_ANY), + basalt::darray({ + VK_EXT_DEBUG_UTILS_EXTENSION_NAME + }, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_ANY) + ); + basalt::Window window(ctx, 640, 480, "Hello Vulkan!");; + basalt::PhysicalDevice phy_dev = basalt::PhysicalDeviceSelector(ctx, window) + .prefer_types(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, 2.0f, 0.0f) + .prefer_types(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, 1.0f, 0.0f) + .ensure_queues(VK_QUEUE_GRAPHICS_BIT, true) + .ensure_swapchain() + .prefer_surface_format({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }) + .prefer_present_mode(VK_PRESENT_MODE_MAILBOX_KHR) + .pick(); + + basalt::Device dev = basalt::DeviceDesigner(ctx, phy_dev) + .request_layer("VK_LAYER_KHRONOS_validation") + .request_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME) + .request_queue(phy_dev.indicies.graphics, 1.0f) + .request_queue(phy_dev.indicies.present, 1.0f) + .design(); + + basalt::Swapchain swapchain(dev, window, + { {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR} }, + { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR } + ); + basalt::RenderPass pass = basalt::RenderPassBuilder(dev) + .add_attachment({ + .format = swapchain.details.cached_format.format, + .samples = VK_SAMPLE_COUNT_1_BIT, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR + }) + .add_subpass(VK_PIPELINE_BIND_POINT_GRAPHICS, { + { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + } + }) + .add_subpass_dependency({ + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT + }) + .build(); + + basalt::Pipeline pipeline = basalt::PipelineBuilder(dev, swapchain.swapchain_extent, VK_NULL_HANDLE) + .add_dynamic_state(VK_DYNAMIC_STATE_SCISSOR) + .add_dynamic_state(VK_DYNAMIC_STATE_VIEWPORT) + .set_render_pass(pass.render_pass) + .add_colour_attachment({ + .blendEnable = VK_FALSE, + .srcColorBlendFactor = VK_BLEND_FACTOR_ONE, + .dstColorBlendFactor = VK_BLEND_FACTOR_ZERO, + .colorBlendOp = VK_BLEND_OP_ADD, + .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, + .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, + .alphaBlendOp = VK_BLEND_OP_ADD, + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }) + .add_shader("shaders/out/simple.vert.spv", VK_SHADER_STAGE_VERTEX_BIT) + .add_shader("shaders/out/simple.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) + .build(); + + swapchain.create_framebuffers(pass.render_pass); + + basalt::CommandPool cmdpool(dev, phy_dev.indicies.graphics); + basalt::darray cmdbufs(swapchain.max_frames_in_flight, MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_32); + for (u32 i = 0; i < swapchain.max_frames_in_flight; ++i) + new (cmdbufs.m_pdata+i) basalt::CommandBuffer(std::move(cmdpool.get_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY))); + cmdbufs.m_nelements = swapchain.max_frames_in_flight; + + u32 mem_str_len = 0; + char* mem_str = nullptr; + basalt::mem::get_memory_usage_string(&mem_str_len, &mem_str); + BINFO("%s\n", mem_str); + basalt::mem::dealloc(mem_str, mem_str_len, MEMORY_TAG_CLASS_STRING | MEMORY_TAG_ZONE_DEBUG | MEMORY_TAG_ALIGN_ANY); + + VkResult err = VK_SUCCESS; + VkRect2D render_area = { .offset = {0,0}, .extent = swapchain.swapchain_extent }; + VkViewport viewport = { + .x = (float)render_area.offset.x, + .y = (float)render_area.offset.y, + .width = (float)render_area.extent.width, + .height = (float)render_area.extent.height, + .minDepth = 0.0f, + .maxDepth = 1.0f + }; while (!window.should_close()) { glfwPollEvents(); + + swapchain.wait_and_reset(); + u32 image_index = swapchain.acquire_next_image(); + + cmdbufs[swapchain.current_frame].reset(); + cmdbufs[swapchain.current_frame].start(pass, swapchain.framebuffers[image_index], render_area); + cmdbufs[swapchain.current_frame].bind_pipeline(pipeline, VK_PIPELINE_BIND_POINT_GRAPHICS); + cmdbufs[swapchain.current_frame].set_scissor(render_area); + cmdbufs[swapchain.current_frame].set_viewport(viewport); + vkCmdDraw(cmdbufs[swapchain.current_frame].vk, 3, 1, 0, 0); + cmdbufs[swapchain.current_frame].stop(); + + VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO}; + VkSemaphore wait_semaphores[] = {swapchain.semaphores_image_available[swapchain.current_frame]}; + VkSemaphore signal_semaphores[] = {swapchain.semaphores_render_finished[image_index]}; + VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &cmdbufs[swapchain.current_frame].vk; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.pWaitDstStageMask = wait_stages; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = signal_semaphores; + VK_ASSERT(vkQueueSubmit(dev.queues[0].queue, 1, &submit_info, swapchain.fences_in_flight[swapchain.current_frame]), "Failed to submit command buffer(s) to queue\n\tAt %s:%d\n\tError %s\n"); + VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; + present_info.pNext = VK_NULL_HANDLE; + present_info.pResults = VK_NULL_HANDLE; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = signal_semaphores; + present_info.swapchainCount = 1; + present_info.pSwapchains = &swapchain.swapchain; + present_info.pImageIndices = &image_index; + + VK_ASSERT(vkQueuePresentKHR(dev.queues[1].queue, &present_info), "Failed to queue presentation of rendered frame\n\tAt %s:%d\n\tError %s\n"); + swapchain.current_frame = (swapchain.current_frame + 1) % swapchain.max_frames_in_flight; } + cmdbufs.resize(0); +} + +int main() +{ + initialize_logger(); + basalt::mem::initialize_memory(); + glfwInit(); + logger_set_global_mask(LOG_MASK_ALL); + logger_set_mask(logger_find_stream(stdout), LOG_DEBUG | LOG_MASK_INFO | LOG_TRACE); + + application(); + + u32 mem_str_len = 0; + char* mem_str = nullptr; + basalt::mem::get_memory_usage_string(&mem_str_len, &mem_str); + BINFO("%s\n", mem_str); + basalt::mem::dealloc(mem_str, mem_str_len, MEMORY_TAG_CLASS_STRING | MEMORY_TAG_ZONE_DEBUG | MEMORY_TAG_ALIGN_ANY); + + glfwTerminate(); + basalt::mem::terminate_memory(); + terminate_logger(); return 0; } + \ No newline at end of file