From 35347d28e043ddd65b8bf0f788f85d9e3f8f3dcd Mon Sep 17 00:00:00 2001 From: Anish Bhobe Date: Thu, 12 Jun 2025 19:12:12 +0200 Subject: [PATCH] Using custom alloctor. --- AppState.cpp | 64 +++++++ AppState.h | 30 ++++ Blaze.cpp | 375 +++--------------------------------------- Blaze.vcxproj | 6 + Blaze.vcxproj.filters | 18 ++ Frame.cpp | 6 +- Frame.h | 3 +- GlobalMemory.cpp | 65 ++++++++ GlobalMemory.h | 34 ++++ MiscData.cpp | 290 ++++++++++++++++++++++++++++++++ MiscData.h | 19 +++ RenderDevice.cpp | 156 +++++++++++------- RenderDevice.h | 34 +++- 13 files changed, 678 insertions(+), 422 deletions(-) create mode 100644 AppState.cpp create mode 100644 AppState.h create mode 100644 GlobalMemory.cpp create mode 100644 GlobalMemory.h create mode 100644 MiscData.cpp create mode 100644 MiscData.h diff --git a/AppState.cpp b/AppState.cpp new file mode 100644 index 0000000..49daffe --- /dev/null +++ b/AppState.cpp @@ -0,0 +1,64 @@ +#include "AppState.h" + +#include + +#include "GlobalMemory.h" +#include "RenderDevice.h" +#include "MiscData.h" + +bool AppState::isInit() const +{ + return window and renderDevice and renderDevice->isInit(); +} + +void AppState::cleanup() +{ + if (!isInit()) return; + + renderDevice->waitIdle(); + + Take(miscData)->cleanup(*renderDevice); + + Take(renderDevice)->cleanup(); + SDL_DestroyWindow(Take(window)); +} + +AppState::AppState(SDL_Window* window, RenderDevice* renderDevice, MiscData* miscData): window{ window } + , renderDevice{ renderDevice } + , miscData{ miscData } +{ +} + +AppState* CreateAppState(GlobalMemory* memory, uint32_t const width, uint32_t const height) +{ + SDL_Window* window = SDL_CreateWindow("Blaze Test", static_cast(width), static_cast(height), SDL_WINDOW_VULKAN); + if (!window) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); + return nullptr; + } + + auto state = memory->getState(); + RenderDevice* renderDevice = CreateRenderDevice(memory, { .window = window }); + if (!renderDevice->isInit()) + { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "RenderDevice failed to init"); + return nullptr; + } + (void)state; + + auto* miscDataAllocation = memory->allocate(sizeof(MiscData)); + + MiscData* miscData = new (miscDataAllocation) MiscData{}; + miscData->init(*renderDevice); + + auto* allocation = memory->allocate(sizeof(AppState)); + AppState* appState = new (allocation) AppState{ window, renderDevice, miscData }; + + return appState; +} + +AppState::~AppState() +{ + cleanup(); +} diff --git a/AppState.h b/AppState.h new file mode 100644 index 0000000..e693a78 --- /dev/null +++ b/AppState.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +struct GlobalMemory; +struct SDL_Window; +struct RenderDevice; +struct MiscData; + +struct AppState +{ + SDL_Window* window; + RenderDevice* renderDevice; + MiscData* miscData; + + [[nodiscard]] bool isInit() const; + void cleanup(); + + AppState(SDL_Window* window, RenderDevice* renderDevice, MiscData* miscData); + + AppState(AppState const& other) = delete; + AppState(AppState&& other) noexcept = delete; + + AppState& operator=(AppState const& other) = delete; + AppState& operator=(AppState&& other) noexcept = delete; + + ~AppState(); +}; + +AppState* CreateAppState(GlobalMemory* memory, uint32_t const width, uint32_t const height); diff --git a/Blaze.cpp b/Blaze.cpp index 162a982..f6f0b82 100644 --- a/Blaze.cpp +++ b/Blaze.cpp @@ -15,96 +15,50 @@ #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; -struct MiscData +using Byte = uint8_t; + +constexpr size_t operator ""_KiB(size_t const value) { - VkPipelineLayout pipelineLayout; - VkPipeline trianglePipeline; - - VkImageMemoryBarrier2 acquireToRenderBarrier; - VkDependencyInfo acquireToRenderDependency; - VkImageMemoryBarrier2 renderToPresentBarrier; - VkDependencyInfo renderToPresentDependency; - - void init(RenderDevice const& renderDevice); - void cleanup(RenderDevice const& renderDevice); -}; - -struct AppState -{ - SDL_Window* window; - std::unique_ptr renderDevice; - MiscData miscData; - - [[nodiscard]] bool isInit() const; - void cleanup(); - - AppState(); - - AppState(AppState const& other) = delete; - AppState(AppState&& other) noexcept = delete; - - AppState& operator=(AppState const& other) = delete; - AppState& operator=(AppState&& other) noexcept = delete; - - ~AppState(); -}; - -static_assert(sizeof(AppState) < 1024); - -bool AppState::isInit() const -{ - return window and renderDevice and renderDevice->isInit(); + return value * 1024; } -void AppState::cleanup() +constexpr size_t operator ""_MiB(size_t const value) { - if (!isInit()) return; - - renderDevice->waitIdle(); - - miscData.cleanup(*renderDevice); - renderDevice->cleanup(); - SDL_DestroyWindow(window); + return value * 1024_KiB; } -AppState::AppState() +constexpr size_t operator ""_GiB(size_t const value) { - window = SDL_CreateWindow("Blaze Test", WIDTH, HEIGHT, SDL_WINDOW_VULKAN); - if (!window) - { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); - abort(); - } - - renderDevice = std::make_unique(RenderDevice::CreateInfo{ .window = window }); - if (!renderDevice->isInit()) - { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "RenderDevice failed to init"); - abort(); - } - - miscData.init(*renderDevice); + return value * 1024_MiB; } -AppState::~AppState() +namespace Blaze::Global { - cleanup(); + GlobalMemory g_Memory; } SDL_AppResult SDL_AppInit(void** pAppState, int, char**) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); - *pAppState = new AppState{}; + 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()) @@ -119,7 +73,7 @@ SDL_AppResult SDL_AppIterate(void* appstate) { AppState& appState = *static_cast(appstate); RenderDevice& renderDevice = *appState.renderDevice; - MiscData& misc = appState.miscData; + MiscData& misc = *appState.miscData; Frame& currentFrame = renderDevice.frames[renderDevice.frameIndex]; VK_CHECK(vkWaitForFences(renderDevice.device, 1, ¤tFrame.frameReadyToReuse, VK_TRUE, std::numeric_limits::max())); @@ -247,292 +201,9 @@ SDL_AppResult SDL_AppEvent(void*, SDL_Event* event) void SDL_AppQuit(void* appstate, SDL_AppResult) { - AppState *appState = static_cast (appstate); + AppState* appState = static_cast (appstate); appState->cleanup(); - // Not necessary, this memory will be winked out. - delete appState; -} - -void MiscData::init(RenderDevice const& renderDevice) -{ - VkDevice const device = renderDevice.device; - { - size_t dataSize; - void* rawData = SDL_LoadFile("Triangle.spv", &dataSize); - ASSERT(dataSize % 4 == 0); - - if (not rawData) - { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "%s", SDL_GetError()); - abort(); - } - - auto data = static_cast(rawData); - - VkShaderModuleCreateInfo const shaderModuleCreateInfo = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .codeSize = dataSize, - .pCode = data, - }; - - VkShaderModule shaderModule; - VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule)); - - VkPipelineLayoutCreateInfo constexpr pipelineLayoutCreateInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .setLayoutCount = 0, - .pSetLayouts = nullptr, - .pushConstantRangeCount = 0, - .pPushConstantRanges = nullptr, - }; - VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - - std::array stages = { - VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .stage = VK_SHADER_STAGE_VERTEX_BIT, - .module = shaderModule, - .pName = "VertexMain", - .pSpecializationInfo = nullptr, - }, - VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = shaderModule, - .pName = "FragmentMain", - .pSpecializationInfo = nullptr, - } - }; - - VkPipelineVertexInputStateCreateInfo constexpr vertexInputState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .vertexBindingDescriptionCount = 0, - .pVertexBindingDescriptions = nullptr, - .vertexAttributeDescriptionCount = 0, - .pVertexAttributeDescriptions = nullptr, - }; - - VkPipelineInputAssemblyStateCreateInfo constexpr inputAssembly = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = VK_FALSE, - }; - - VkPipelineTessellationStateCreateInfo constexpr tessellationState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .patchControlPoints = 0, - }; - - VkPipelineViewportStateCreateInfo constexpr viewportState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .viewportCount = 1, - .pViewports = nullptr, - .scissorCount = 1, - .pScissors = nullptr, - }; - - VkPipelineRasterizationStateCreateInfo constexpr rasterizationState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .depthClampEnable = VK_TRUE, - .rasterizerDiscardEnable = VK_FALSE, - .polygonMode = VK_POLYGON_MODE_FILL, - .cullMode = VK_CULL_MODE_NONE, - .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, - .depthBiasEnable = VK_FALSE, - .depthBiasConstantFactor = 0.0f, - .depthBiasClamp = 0.0f, - .depthBiasSlopeFactor = 0.0f, - .lineWidth = 1.0f, - }; - - VkPipelineMultisampleStateCreateInfo constexpr multisampleState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - .sampleShadingEnable = VK_FALSE, - .minSampleShading = 0.0f, - .pSampleMask = nullptr, - .alphaToCoverageEnable = VK_FALSE, - .alphaToOneEnable = VK_FALSE, - }; - - VkPipelineDepthStencilStateCreateInfo constexpr depthStencilState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .depthTestEnable = VK_FALSE, - .depthWriteEnable = VK_FALSE, - .depthCompareOp = VK_COMPARE_OP_ALWAYS, - .depthBoundsTestEnable = VK_FALSE, - .stencilTestEnable = VK_FALSE, - .front = {}, - .back = {}, - .minDepthBounds = 0.0f, - .maxDepthBounds = 1.0f, - }; - - VkPipelineColorBlendAttachmentState constexpr colorBlendAttachmentState = { - .blendEnable = VK_FALSE, - .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, - .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - .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, - }; - - VkPipelineColorBlendStateCreateInfo const colorBlendState = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .logicOpEnable = VK_FALSE, - .logicOp = VK_LOGIC_OP_COPY, - .attachmentCount = 1, - .pAttachments = &colorBlendAttachmentState, - .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, - }; - - std::array constexpr dynamicStates = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - }; - - VkPipelineDynamicStateCreateInfo const dynamicStateCreateInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .dynamicStateCount = static_cast(dynamicStates.size()), - .pDynamicStates = dynamicStates.data() - }; - - VkPipelineRenderingCreateInfoKHR const renderingCreateInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &renderDevice.swapchainFormat, - }; - - VkGraphicsPipelineCreateInfo const graphicsPipelineCreateInfo = { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = &renderingCreateInfo, - .flags = 0, - .stageCount = static_cast(stages.size()), - .pStages = stages.data(), - .pVertexInputState = &vertexInputState, - .pInputAssemblyState = &inputAssembly, - .pTessellationState = &tessellationState, - .pViewportState = &viewportState, - .pRasterizationState = &rasterizationState, - .pMultisampleState = &multisampleState, - .pDepthStencilState = &depthStencilState, - .pColorBlendState = &colorBlendState, - .pDynamicState = &dynamicStateCreateInfo, - .layout = pipelineLayout, - .renderPass = nullptr, - .subpass = 0, - .basePipelineHandle = nullptr, - .basePipelineIndex = 0, - }; - - VK_CHECK(vkCreateGraphicsPipelines(device, nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &trianglePipeline)); - - vkDestroyShaderModule(device, shaderModule, nullptr); - - SDL_free(rawData); - } - - acquireToRenderBarrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - } - }; - acquireToRenderDependency = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = 0, - .memoryBarrierCount = 0, - .pMemoryBarriers = nullptr, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = nullptr, - .imageMemoryBarrierCount = 1, - .pImageMemoryBarriers = &acquireToRenderBarrier, - }; - - renderToPresentBarrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, - .dstAccessMask = VK_ACCESS_2_NONE, - .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - } - }; - renderToPresentDependency = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = 0, - .memoryBarrierCount = 0, - .pMemoryBarriers = nullptr, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = nullptr, - .imageMemoryBarrierCount = 1, - .pImageMemoryBarriers = &renderToPresentBarrier, - }; - -} - -void MiscData::cleanup(RenderDevice const& renderDevice) -{ - VkDevice const device = renderDevice.device; - - vkDestroyPipeline(device, trianglePipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); -} + Blaze::Global::g_Memory.destroy(); +} \ No newline at end of file diff --git a/Blaze.vcxproj b/Blaze.vcxproj index b9659c6..352a156 100644 --- a/Blaze.vcxproj +++ b/Blaze.vcxproj @@ -148,8 +148,11 @@ + + + @@ -176,10 +179,13 @@ + + + diff --git a/Blaze.vcxproj.filters b/Blaze.vcxproj.filters index f1a08ec..a7a61f6 100644 --- a/Blaze.vcxproj.filters +++ b/Blaze.vcxproj.filters @@ -27,6 +27,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -66,5 +75,14 @@ Header Files + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/Frame.cpp b/Frame.cpp index a22bdf9..372289a 100644 --- a/Frame.cpp +++ b/Frame.cpp @@ -10,15 +10,13 @@ bool Frame::isInit() const return static_cast(commandPool); } -Frame::Frame(RenderDevice const& renderDevice) +Frame::Frame(VkDevice const device, uint32_t const directQueueFamilyIndex) { - VkDevice const device = renderDevice.device; - VkCommandPoolCreateInfo const commandPoolCreateInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .pNext = nullptr, .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = renderDevice.directQueueFamilyIndex, + .queueFamilyIndex = directQueueFamilyIndex, }; VK_CHECK(vkCreateCommandPool(device, &commandPoolCreateInfo, nullptr, &commandPool)); diff --git a/Frame.h b/Frame.h index 0926393..99d26f9 100644 --- a/Frame.h +++ b/Frame.h @@ -15,11 +15,10 @@ struct Frame [[nodiscard]] bool isInit() const; - explicit Frame(RenderDevice const& renderDevice); + Frame(VkDevice device, uint32_t directQueueFamilyIndex); void cleanup(RenderDevice const& renderDevice); ~Frame(); }; - diff --git a/GlobalMemory.cpp b/GlobalMemory.cpp new file mode 100644 index 0000000..dec7719 --- /dev/null +++ b/GlobalMemory.cpp @@ -0,0 +1,65 @@ +#include "GlobalMemory.h" + +#include + +void GlobalMemory::init(size_t const size) +{ + memory = new Byte[size]; + capacity = size; + available = size; +} + +void GlobalMemory::destroy() +{ + Byte const* originalMemory = memory - (capacity - available); + delete[] originalMemory; + memory = nullptr; + available = 0; + capacity = 0; +} + +Byte* GlobalMemory::allocate(size_t const size) +{ + assert(size <= available && "No enough space available"); + + Byte* retVal = memory; + memory += size; + available -= size; + SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "ALLOC: %p -> %p (%llu) (avail: %llu)", reinterpret_cast(retVal), reinterpret_cast(memory), size, available); + + return retVal; +} + +Byte* GlobalMemory::allocate(size_t const size, size_t const alignment) +{ + uintptr_t const addr = reinterpret_cast(memory); + uintptr_t const foundOffset = addr % alignment; + + if (foundOffset == 0) + { + return allocate(size); + } + + uintptr_t const offset = alignment - foundOffset; + size_t const allocationSize = size + offset; + + return offset + allocate(allocationSize); +} + +GlobalMemory::State GlobalMemory::getState() const +{ + SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "TEMP: %p %llu", reinterpret_cast(memory), available); + return { + .memory = memory, + .available = available, + }; +} + +void GlobalMemory::restoreState(State const& state) +{ + assert(memory >= state.memory); //< Behind top of allocator + assert(memory - (capacity - available) <= state.memory); //< Ahead of start of allocator + SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "RESTORE: %p %llu", reinterpret_cast(memory), available); + memory = state.memory; + available = state.available; +} diff --git a/GlobalMemory.h b/GlobalMemory.h new file mode 100644 index 0000000..29e30e2 --- /dev/null +++ b/GlobalMemory.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "MacroUtils.h" + +using Byte = uint8_t; + +struct GlobalMemory +{ + struct State + { + Byte* memory; + size_t available; + }; + + Byte* memory; + size_t available; + size_t capacity; + + void init(size_t const size); + + void destroy(); + + Byte* allocate(size_t const size); + + Byte* allocate(size_t const size, size_t const alignment); + + // Do not do any permanent allocations after calling this. + [[nodiscard]] State getState() const; + + // Call this before permanent allocations. + void restoreState(State const& state); +}; \ No newline at end of file diff --git a/MiscData.cpp b/MiscData.cpp new file mode 100644 index 0000000..4ac2060 --- /dev/null +++ b/MiscData.cpp @@ -0,0 +1,290 @@ +#include "MiscData.h" + +#include +#include + +#include "MacroUtils.h" +#include "RenderDevice.h" + + +void MiscData::init(RenderDevice const& renderDevice) +{ + VkDevice const device = renderDevice.device; + { + size_t dataSize; + void* rawData = SDL_LoadFile("Triangle.spv", &dataSize); + ASSERT(dataSize % 4 == 0); + + if (not rawData) + { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "%s", SDL_GetError()); + abort(); + } + + auto data = static_cast(rawData); + + VkShaderModuleCreateInfo const shaderModuleCreateInfo = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .codeSize = dataSize, + .pCode = data, + }; + + VkShaderModule shaderModule; + VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule)); + + VkPipelineLayoutCreateInfo constexpr pipelineLayoutCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .setLayoutCount = 0, + .pSetLayouts = nullptr, + .pushConstantRangeCount = 0, + .pPushConstantRanges = nullptr, + }; + VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + std::array stages = { + VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = shaderModule, + .pName = "VertexMain", + .pSpecializationInfo = nullptr, + }, + VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = shaderModule, + .pName = "FragmentMain", + .pSpecializationInfo = nullptr, + } + }; + + VkPipelineVertexInputStateCreateInfo constexpr vertexInputState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .vertexBindingDescriptionCount = 0, + .pVertexBindingDescriptions = nullptr, + .vertexAttributeDescriptionCount = 0, + .pVertexAttributeDescriptions = nullptr, + }; + + VkPipelineInputAssemblyStateCreateInfo constexpr inputAssembly = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineTessellationStateCreateInfo constexpr tessellationState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .patchControlPoints = 0, + }; + + VkPipelineViewportStateCreateInfo constexpr viewportState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .viewportCount = 1, + .pViewports = nullptr, + .scissorCount = 1, + .pScissors = nullptr, + }; + + VkPipelineRasterizationStateCreateInfo constexpr rasterizationState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .depthClampEnable = VK_TRUE, + .rasterizerDiscardEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .cullMode = VK_CULL_MODE_NONE, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .depthBiasEnable = VK_FALSE, + .depthBiasConstantFactor = 0.0f, + .depthBiasClamp = 0.0f, + .depthBiasSlopeFactor = 0.0f, + .lineWidth = 1.0f, + }; + + VkPipelineMultisampleStateCreateInfo constexpr multisampleState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .sampleShadingEnable = VK_FALSE, + .minSampleShading = 0.0f, + .pSampleMask = nullptr, + .alphaToCoverageEnable = VK_FALSE, + .alphaToOneEnable = VK_FALSE, + }; + + VkPipelineDepthStencilStateCreateInfo constexpr depthStencilState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .depthTestEnable = VK_FALSE, + .depthWriteEnable = VK_FALSE, + .depthCompareOp = VK_COMPARE_OP_ALWAYS, + .depthBoundsTestEnable = VK_FALSE, + .stencilTestEnable = VK_FALSE, + .front = {}, + .back = {}, + .minDepthBounds = 0.0f, + .maxDepthBounds = 1.0f, + }; + + VkPipelineColorBlendAttachmentState constexpr colorBlendAttachmentState = { + .blendEnable = VK_FALSE, + .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, + .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .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, + }; + + VkPipelineColorBlendStateCreateInfo const colorBlendState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = 1, + .pAttachments = &colorBlendAttachmentState, + .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, + }; + + std::array constexpr dynamicStates = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo const dynamicStateCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .dynamicStateCount = static_cast(dynamicStates.size()), + .pDynamicStates = dynamicStates.data() + }; + + VkPipelineRenderingCreateInfoKHR const renderingCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &renderDevice.swapchainFormat, + }; + + VkGraphicsPipelineCreateInfo const graphicsPipelineCreateInfo = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &renderingCreateInfo, + .flags = 0, + .stageCount = static_cast(stages.size()), + .pStages = stages.data(), + .pVertexInputState = &vertexInputState, + .pInputAssemblyState = &inputAssembly, + .pTessellationState = &tessellationState, + .pViewportState = &viewportState, + .pRasterizationState = &rasterizationState, + .pMultisampleState = &multisampleState, + .pDepthStencilState = &depthStencilState, + .pColorBlendState = &colorBlendState, + .pDynamicState = &dynamicStateCreateInfo, + .layout = pipelineLayout, + .renderPass = nullptr, + .subpass = 0, + .basePipelineHandle = nullptr, + .basePipelineIndex = 0, + }; + + VK_CHECK(vkCreateGraphicsPipelines(device, nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &trianglePipeline)); + + vkDestroyShaderModule(device, shaderModule, nullptr); + + SDL_free(rawData); + } + + acquireToRenderBarrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + } + }; + acquireToRenderDependency = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &acquireToRenderBarrier, + }; + + renderToPresentBarrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, + .dstAccessMask = VK_ACCESS_2_NONE, + .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + } + }; + renderToPresentDependency = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &renderToPresentBarrier, + }; + +} + +void MiscData::cleanup(RenderDevice const& renderDevice) +{ + VkDevice const device = renderDevice.device; + + vkDestroyPipeline(device, trianglePipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); +} diff --git a/MiscData.h b/MiscData.h new file mode 100644 index 0000000..092e9d0 --- /dev/null +++ b/MiscData.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct RenderDevice; + +struct MiscData +{ + VkPipelineLayout pipelineLayout; + VkPipeline trianglePipeline; + + VkImageMemoryBarrier2 acquireToRenderBarrier; + VkDependencyInfo acquireToRenderDependency; + VkImageMemoryBarrier2 renderToPresentBarrier; + VkDependencyInfo renderToPresentDependency; + + void init(RenderDevice const& renderDevice); + void cleanup(RenderDevice const& renderDevice); +}; diff --git a/RenderDevice.cpp b/RenderDevice.cpp index 0993f09..e004812 100644 --- a/RenderDevice.cpp +++ b/RenderDevice.cpp @@ -5,16 +5,25 @@ #include #include +#include #include "Frame.h" +#include "GlobalMemory.h" #include "MathUtil.h" -RenderDevice::RenderDevice(CreateInfo const& createInfo) +RenderDevice::~RenderDevice() +{ + ASSERT(!isInit()); +} + +// TODO: Failure Handling +RenderDevice* CreateRenderDevice(GlobalMemory* mem, RenderDevice::CreateInfo const& createInfo) { ASSERT(createInfo.window); volkInitialize(); + VkInstance instance; // Create Instance { VkApplicationInfo constexpr applicationInfo = { @@ -45,28 +54,35 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) volkLoadInstance(instance); } + VkSurfaceKHR surface; // Create Surface ASSERT(SDL_Vulkan_CreateSurface(createInfo.window, instance, nullptr, &surface)); + VkPhysicalDevice physicalDeviceInUse = nullptr; + VkDevice device = nullptr; + uint32_t directQueueFamilyIndex = -1; + VkQueue directQueue = nullptr; // Create Device and Queue { + auto tempAllocStart = mem->getState(); + uint32_t physicalDeviceCount; VK_CHECK(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr)); - SDL_Log("Found %u GPUs", physicalDeviceCount); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Found %u GPUs", physicalDeviceCount); - std::vector physicalDevices(physicalDeviceCount); - VK_CHECK(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data())); + VkPhysicalDevice* physicalDevices = reinterpret_cast(mem->allocate(sizeof(VkPhysicalDevice) * physicalDeviceCount)); + VK_CHECK(vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices)); - - std::vector queueFamilyProperties; - for (VkPhysicalDevice const physicalDevice : physicalDevices) + for (VkPhysicalDevice const physicalDevice : std::span{ physicalDevices, physicalDeviceCount }) { + auto tempAllocQueueProperties = mem->getState(); + VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(physicalDevice, &properties); - SDL_Log("GPU: %s", properties.deviceName); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "GPU: %s", properties.deviceName); - SDL_Log("- API Version %d.%d.%d", + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "- API Version %d.%d.%d", VK_API_VERSION_MAJOR(properties.apiVersion), VK_API_VERSION_MINOR(properties.apiVersion), VK_API_VERSION_PATCH(properties.apiVersion)); @@ -84,31 +100,34 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) uint32_t queueFamilyCount; vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr); - queueFamilyProperties.resize(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data()); + VkQueueFamilyProperties* queueFamilyProperties = reinterpret_cast(mem->allocate(sizeof(VkQueueFamilyProperties) * queueFamilyCount)); + vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties); - for (uint32_t queueFamilyIndex = 0; VkQueueFamilyProperties const qfp : queueFamilyProperties) + for (uint32_t queueFamilyIndex = 0; queueFamilyIndex != queueFamilyCount; + ++queueFamilyIndex) { + VkQueueFamilyProperties const& qfp = queueFamilyProperties[queueFamilyIndex]; + bool hasGraphicsSupport = false; bool hasComputeSupport = false; bool hasTransferSupport = false; bool hasPresentSupport = false; - SDL_Log("- Queue [%d]", queueFamilyIndex); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "- Queue [%d]", queueFamilyIndex); if (qfp.queueFlags & VK_QUEUE_GRAPHICS_BIT) { hasGraphicsSupport = true; - SDL_Log("-- Graphic"); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "-- Graphic"); } if (qfp.queueFlags & VK_QUEUE_COMPUTE_BIT) { hasComputeSupport = true; - SDL_Log("-- Compute"); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "-- Compute"); } if (qfp.queueFlags & VK_QUEUE_TRANSFER_BIT) { hasTransferSupport = true; - SDL_Log("-- Transfer"); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "-- Transfer"); } VkBool32 isSurfaceSupported; @@ -117,7 +136,7 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) if (isSurfaceSupported) { hasPresentSupport = true; - SDL_Log("-- Present"); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "-- Present"); } if (hasGraphicsSupport and hasComputeSupport and hasTransferSupport and hasPresentSupport) @@ -127,8 +146,9 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) break; } - ++queueFamilyIndex; } + + mem->restoreState(tempAllocQueueProperties); } ASSERT(physicalDeviceInUse); @@ -174,21 +194,30 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) VK_CHECK(vkCreateDevice(physicalDeviceInUse, &deviceCreateInfo, nullptr, &device)); vkGetDeviceQueue(device, directQueueFamilyIndex, 0, &directQueue); + + mem->restoreState(tempAllocStart); } // Swapchain creation - swapchainExtent = { createInfo.width, createInfo.height }; + VkExtent2D swapchainExtent = { createInfo.width, createInfo.height }; + VkFormat swapchainFormat = VK_FORMAT_UNDEFINED; + VkSwapchainKHR swapchain; + VkImage* swapchainImages; + VkImageView* swapchainViews; + uint32_t swapchainImageCount; { + auto tempAllocStart = mem->getState(); + VkSurfaceCapabilitiesKHR capabilities; VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDeviceInUse, surface, &capabilities)); // Image Count Calculation - uint32_t swapchainImageCount = 3; + swapchainImageCount = 3; if (capabilities.maxImageCount > 0) { swapchainImageCount = std::min(swapchainImageCount, capabilities.maxImageCount); } - swapchainImageCount = std::max(swapchainImageCount, capabilities.minImageCount); + swapchainImageCount = std::max(swapchainImageCount, capabilities.minImageCount + 1); // Image Size calculation { @@ -200,18 +229,18 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) uint32_t surfaceFormatCount; vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDeviceInUse, surface, &surfaceFormatCount, nullptr); - std::vector surfaceFormats(surfaceFormatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDeviceInUse, surface, &surfaceFormatCount, surfaceFormats.data()); + VkSurfaceFormatKHR* surfaceFormats = reinterpret_cast(mem->allocate(sizeof(VkSurfaceFormatKHR*) * surfaceFormatCount)); + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDeviceInUse, surface, &surfaceFormatCount, surfaceFormats); VkSurfaceFormatKHR format = { .format = VK_FORMAT_UNDEFINED, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, }; - for (auto& surfaceFormat : surfaceFormats) + for (auto& surfaceFormat : std::span{ surfaceFormats, surfaceFormatCount }) { if (surfaceFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - SDL_Log("Color Space SRGB Found %d", surfaceFormat.format); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Color Space SRGB Found %d", surfaceFormat.format); if (surfaceFormat.format == VK_FORMAT_R8G8B8A8_SRGB) { format = surfaceFormat; break; @@ -230,11 +259,11 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) uint32_t presentModeCount; vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDeviceInUse, surface, &presentModeCount, nullptr); - std::vector presentModes(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDeviceInUse, surface, &presentModeCount, presentModes.data()); + VkPresentModeKHR* presentModes = reinterpret_cast(mem->allocate(sizeof(VkPresentModeKHR*) * presentModeCount)); + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDeviceInUse, surface, &presentModeCount, presentModes); VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; - for (VkPresentModeKHR presentModeIter : presentModes) + for (VkPresentModeKHR presentModeIter : std::span{ presentModes, presentModeCount }) { if (presentModeIter == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { @@ -248,6 +277,8 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) } } + mem->restoreState(tempAllocStart); + VkSwapchainCreateInfoKHR const swapchainCreateInfo = { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = nullptr, @@ -273,18 +304,16 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) swapchainImageCount = 0; vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, nullptr); - SDL_Log("%llu", swapchainImages.size()); - swapchainImages.resize(swapchainImageCount); - vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages.data()); - - swapchainViews.reserve(swapchainImageCount); - for (auto& image : swapchainImages) { + swapchainImages = reinterpret_cast(mem->allocate(sizeof(VkImage) * swapchainImageCount)); + vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages); + swapchainViews = reinterpret_cast(mem->allocate(sizeof(VkImageView) * swapchainImageCount)); + for (uint32_t i = 0; i != swapchainImageCount; ++i) { VkImageViewCreateInfo const viewCreateInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = nullptr, .flags = 0, - .image = image, + .image = swapchainImages[i], .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = format.format, .components = { @@ -302,26 +331,24 @@ RenderDevice::RenderDevice(CreateInfo const& createInfo) } }; - VkImageView view; - VK_CHECK(vkCreateImageView(device, &viewCreateInfo, nullptr, &view)); - swapchainViews.push_back(view); + VK_CHECK(vkCreateImageView(device, &viewCreateInfo, nullptr, &swapchainViews[i])); } } // Init frames. - { - auto count = static_cast(swapchainImages.size()); - frames.reserve(count); - for (uint32_t i = 0; i != count; ++i) - { - frames.emplace_back(*this); - } - } -} -RenderDevice::~RenderDevice() -{ - cleanup(); + Frame* frames = reinterpret_cast(mem->allocate(sizeof(Frame) * swapchainImageCount)); + for (uint32_t i = 0; i != swapchainImageCount; ++i) + { + new (frames + i) Frame(device, directQueueFamilyIndex); + } + + Byte* allocation = mem->allocate(sizeof(RenderDevice), alignof(RenderDevice)); + return new (allocation) RenderDevice{ + instance, surface, physicalDeviceInUse, + device, directQueue, directQueueFamilyIndex, + swapchainFormat, swapchainExtent, swapchain, swapchainImages, swapchainViews, frames, swapchainImageCount, + }; } inline bool RenderDevice::isInit() const @@ -334,18 +361,15 @@ void RenderDevice::cleanup() if (not isInit()) return; - for (Frame& frame : frames) + for (Frame& frame : std::span{ frames, swapchainImageCount }) { frame.cleanup(*this); } - frames.clear(); - for (auto const& view : swapchainViews) + for (auto const& view : std::span{ swapchainViews, swapchainImageCount }) { vkDestroyImageView(device, view, nullptr); } - swapchainViews.clear(); - swapchainImages.clear(); vkDestroySwapchainKHR(device, Take(swapchain), nullptr); @@ -365,5 +389,25 @@ void RenderDevice::waitIdle() const uint32_t RenderDevice::getNumFrames() const { - return static_cast(frames.size()); + return swapchainImageCount; +} + +RenderDevice::RenderDevice(VkInstance const instance, VkSurfaceKHR const surface, VkPhysicalDevice const physicalDeviceInUse, + VkDevice const device, VkQueue const directQueue, uint32_t const directQueueFamilyIndex, VkFormat const swapchainFormat, + VkExtent2D const swapchainExtent, VkSwapchainKHR const swapchain, VkImage* swapchainImages, VkImageView* swapchainViews, + Frame* frames, uint32_t const swapchainImageCount) + : instance{ instance } + , surface{ surface } + , physicalDeviceInUse{ physicalDeviceInUse } + , device{ device } + , directQueue{ directQueue } + , directQueueFamilyIndex{ directQueueFamilyIndex } + , swapchainFormat{ swapchainFormat } + , swapchainExtent{ swapchainExtent } + , swapchain{ swapchain } + , swapchainImages{ swapchainImages } + , swapchainViews{ swapchainViews } + , frames{ frames } + , swapchainImageCount{ swapchainImageCount } +{ } diff --git a/RenderDevice.h b/RenderDevice.h index 2749792..fef80bf 100644 --- a/RenderDevice.h +++ b/RenderDevice.h @@ -2,11 +2,10 @@ #include -#include - #include #include +struct GlobalMemory; struct Frame; /// The Rendering backend abstraction @@ -33,10 +32,10 @@ struct RenderDevice VkFormat swapchainFormat; VkExtent2D swapchainExtent; VkSwapchainKHR swapchain; - std::vector swapchainImages; - std::vector swapchainViews; - - std::vector frames; + VkImage* swapchainImages; + VkImageView* swapchainViews; + Frame* frames; + uint32_t swapchainImageCount; uint32_t frameIndex = 0; [[nodiscard]] bool isInit() const; @@ -44,7 +43,24 @@ struct RenderDevice void waitIdle() const; [[nodiscard]] uint32_t getNumFrames() const; - explicit RenderDevice(CreateInfo const& createInfo); + RenderDevice( + VkInstance instance, + VkSurfaceKHR surface, + VkPhysicalDevice physicalDeviceInUse, + VkDevice device, + VkQueue directQueue, + uint32_t directQueueFamilyIndex, + // TODO: Pack? + + VkFormat swapchainFormat, + VkExtent2D swapchainExtent, + VkSwapchainKHR swapchain, + + VkImage* swapchainImages, + VkImageView* swapchainViews, + Frame* frames, + uint32_t swapchainImageCount + ); RenderDevice(RenderDevice const&) = delete; RenderDevice& operator=(RenderDevice const&) = delete; @@ -53,4 +69,6 @@ struct RenderDevice RenderDevice& operator=(RenderDevice&&) noexcept = delete; ~RenderDevice(); -}; \ No newline at end of file +}; + +RenderDevice* CreateRenderDevice(GlobalMemory* mem, RenderDevice::CreateInfo const& createInfo); \ No newline at end of file