// Blaze.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include #include #include #include #define SDL_MAIN_USE_CALLBACKS 1 #include #include #include #include #include #include "AppState.h" #include "Frame.h" #include "GlobalMemory.h" #include "MacroUtils.h" #include "MathUtil.h" #include "RenderDevice.h" #include "MiscData.h" constexpr uint32_t WIDTH = 1280; constexpr uint32_t HEIGHT = 720; constexpr uint32_t NUM_FRAMES = 3; using Byte = uint8_t; constexpr size_t operator ""_KiB(size_t const value) { return value * 1024; } constexpr size_t operator ""_MiB(size_t const value) { return value * 1024_KiB; } constexpr size_t operator ""_GiB(size_t const value) { return value * 1024_MiB; } namespace Blaze::Global { GlobalMemory g_Memory; } SDL_AppResult SDL_AppInit(void** pAppState, int, char**) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); Blaze::Global::g_Memory.init(128_MiB); *pAppState = CreateAppState(&Blaze::Global::g_Memory, WIDTH, HEIGHT); if (!*pAppState) return SDL_APP_FAILURE; AppState& appState = *static_cast(*pAppState); if (!appState.isInit()) { return SDL_APP_FAILURE; } return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppIterate(void* appstate) { AppState& appState = *static_cast(appstate); RenderDevice& renderDevice = *appState.renderDevice; MiscData& misc = *appState.miscData; Frame& currentFrame = renderDevice.frames[renderDevice.frameIndex]; VK_CHECK(vkWaitForFences(renderDevice.device, 1, ¤tFrame.frameReadyToReuse, VK_TRUE, std::numeric_limits::max())); // All resources of frame 'frameIndex' are free. uint32_t currentImageIndex; VK_CHECK(vkAcquireNextImageKHR(renderDevice.device, renderDevice.swapchain, std::numeric_limits::max(), currentFrame.imageAcquiredSemaphore, nullptr, ¤tImageIndex)); VK_CHECK(vkResetFences(renderDevice.device, 1, ¤tFrame.frameReadyToReuse)); VK_CHECK(vkResetCommandPool(renderDevice.device, currentFrame.commandPool, 0)); misc.acquireToRenderBarrier.image = renderDevice.swapchainImages[currentImageIndex]; misc.renderToPresentBarrier.image = renderDevice.swapchainImages[currentImageIndex]; VkCommandBuffer cmd = currentFrame.commandBuffer; VkCommandBufferBeginInfo constexpr beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .pNext = nullptr, .flags = 0, .pInheritanceInfo = nullptr, }; VkClearColorValue constexpr static BLACK_CLEAR = { .float32 = { 0.0f, 0.0f, 0.0f, 1.0f }, }; VK_CHECK(vkBeginCommandBuffer(cmd, &beginInfo)); { VkRenderingAttachmentInfo const attachmentInfo = { .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .pNext = nullptr, .imageView = renderDevice.swapchainViews[currentImageIndex], .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .resolveMode = VK_RESOLVE_MODE_NONE, .resolveImageView = nullptr, .resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .clearValue = {.color = BLACK_CLEAR}, }; VkRenderingInfo renderingInfo = { .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, .pNext = nullptr, .flags = 0, .renderArea = {.offset = {0,0}, .extent = renderDevice.swapchainExtent}, .layerCount = 1, .viewMask = 0, .colorAttachmentCount = 1, .pColorAttachments = &attachmentInfo, .pDepthAttachment = nullptr, .pStencilAttachment = nullptr, }; vkCmdPipelineBarrier2(cmd, &misc.acquireToRenderDependency); vkCmdBeginRendering(cmd, &renderingInfo); { VkViewport viewport = { .x = 0, .y = static_cast(renderDevice.swapchainExtent.height), .width = static_cast(renderDevice.swapchainExtent.width), .height = -static_cast(renderDevice.swapchainExtent.height), .minDepth = 0.0f, .maxDepth = 1.0f, }; vkCmdSetViewport(cmd, 0, 1, &viewport); VkRect2D scissor = { .offset = {0, 0}, .extent = renderDevice.swapchainExtent, }; vkCmdSetScissor(cmd, 0, 1, &scissor); // Render Something? vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, misc.trianglePipeline); vkCmdDraw(cmd, 3, 1, 0, 0); } vkCmdEndRendering(cmd); vkCmdPipelineBarrier2(cmd, &misc.renderToPresentDependency); } VK_CHECK(vkEndCommandBuffer(cmd)); VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo const submitInfo = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 1, .pWaitSemaphores = ¤tFrame.imageAcquiredSemaphore, .pWaitDstStageMask = &stageMask, .commandBufferCount = 1, .pCommandBuffers = &cmd, .signalSemaphoreCount = 1, .pSignalSemaphores = ¤tFrame.renderFinishedSemaphore, }; VK_CHECK(vkQueueSubmit(renderDevice.directQueue, 1, &submitInfo, currentFrame.frameReadyToReuse)); VkPresentInfoKHR const presentInfo = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, .waitSemaphoreCount = 1, .pWaitSemaphores = ¤tFrame.renderFinishedSemaphore, .swapchainCount = 1, .pSwapchains = &renderDevice.swapchain, .pImageIndices = ¤tImageIndex, .pResults = nullptr, }; VK_CHECK(vkQueuePresentKHR(renderDevice.directQueue, &presentInfo)); renderDevice.frameIndex = (renderDevice.frameIndex + 1) % NUM_FRAMES; return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppEvent(void*, SDL_Event* event) { if (event->type == SDL_EVENT_QUIT) { return SDL_APP_SUCCESS; } return SDL_APP_CONTINUE; } void SDL_AppQuit(void* appstate, SDL_AppResult) { AppState* appState = static_cast (appstate); appState->cleanup(); Blaze::Global::g_Memory.destroy(); }