From 7507394af917d3ad401862614ab8dfb34cd507e9 Mon Sep 17 00:00:00 2001 From: Anish Bhobe Date: Sat, 3 May 2025 13:44:47 +0200 Subject: [PATCH] Added Pipeline creation into the Device. --- aster/include/aster/core/config.h | 1 + aster/include/aster/systems/device.h | 199 ++++++++--------------- aster/include/aster/util/CMakeLists.txt | 3 +- aster/include/aster/util/files.h | 15 ++ aster/src/aster/systems/device.cpp | 201 +++++++++++++++++++++++- aster/src/aster/util/CMakeLists.txt | 2 +- aster/src/aster/util/files.cpp | 79 ++++++++++ samples/00_util/helpers.cpp | 73 --------- samples/00_util/helpers.h | 3 - samples/01_triangle/triangle.cpp | 182 ++++----------------- 10 files changed, 393 insertions(+), 365 deletions(-) create mode 100644 aster/include/aster/util/files.h create mode 100644 aster/src/aster/util/files.cpp diff --git a/aster/include/aster/core/config.h b/aster/include/aster/core/config.h index 2a626e0..d37d98c 100644 --- a/aster/include/aster/core/config.h +++ b/aster/include/aster/core/config.h @@ -16,6 +16,7 @@ #define VULKAN_HPP_DISABLE_ENHANCED_MODE 1 #define VULKAN_HPP_NO_EXCEPTIONS 1 #define VULKAN_HPP_NO_SMART_HANDLE 1 +#define VULKAN_HPP_NO_STRUCT_SETTERS 1 #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 diff --git a/aster/include/aster/systems/device.h b/aster/include/aster/systems/device.h index 1790074..0b0d99b 100644 --- a/aster/include/aster/systems/device.h +++ b/aster/include/aster/systems/device.h @@ -12,9 +12,9 @@ #include "aster/core/image_view.h" #include "aster/core/instance.h" #include "aster/core/physical_device.h" +#include "aster/core/pipeline.h" #include "aster/core/sampler.h" #include "aster/core/swapchain.h" -#include "aster/core/pipeline.h" #include #include @@ -25,7 +25,6 @@ constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3; struct Window; -using CoreDevice = Device; template <> struct eastl::hash @@ -226,7 +225,61 @@ struct SamplerCreateInfo #pragma region Pipeline // ---------------------------------------------------------------------------------------------------- -// TODO +struct AttributeInfo +{ + u32 m_Location; + u32 m_Offset; + enum class Format + { + eFloat32X4, + eFloat32X3, + eFloat32X2, + eFloat32, + } m_Format; + + [[nodiscard]] vk::Format + GetFormat() const + { + switch (m_Format) + { + case Format::eFloat32X4: + return vk::Format::eR32G32B32A32Sfloat; + case Format::eFloat32X3: + return vk::Format::eR32G32B32Sfloat; + case Format::eFloat32X2: + return vk::Format::eR32G32Sfloat; + case Format::eFloat32: + return vk::Format::eR32Sfloat; + } + return vk::Format::eUndefined; + } +}; + +struct VertexInput +{ + eastl::vector m_Attribute; + u32 m_Stride; + bool m_IsPerInstance; +}; + +struct GraphicsShaderModuleInfo +{ + std::string_view m_ShaderFile; + std::string_view m_EntryPoint; + enum class Type + { + eVertex = vk::ShaderStageFlagBits::eVertex, + eFragment = vk::ShaderStageFlagBits::eFragment, + eTesselationControl = vk::ShaderStageFlagBits::eTessellationControl, + eTesselationEvaluation = vk::ShaderStageFlagBits::eTessellationEvaluation, + } m_Type; +}; + +struct GraphicsPipelineCreateInfo +{ + eastl::fixed_vector m_VertexInputs; + eastl::fixed_vector m_ShaderModules; +}; #pragma endregion @@ -291,7 +344,7 @@ class GraphicsContext : public Context public: DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport); void BindVertexBuffer(const Ref &vertexBuffer); - DEPRECATE_RAW_CALLS void BindPipeline(vk::Pipeline pipeline); + void BindPipeline(const Pipeline &pipeline); void Draw(u32 vertexCount); void DrawIndexed(u32 indexCount); @@ -311,8 +364,9 @@ struct Frame vk::Semaphore m_RenderFinishSem; u32 m_FrameIdx; + eastl::vector m_CommandBuffers; + // Transient - u32 m_ImageIdx; vk::Image m_SwapchainImage; vk::ImageView m_SwapchainImageView; u32 m_ImageIdx; @@ -428,132 +482,13 @@ class Device final // Pipeline // ---------------------------------------------------------------------------------------------------- - /* - Pipeline CreatePipeline() - { - // Pipeline Setup - auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE); - auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE); + // TODO: Cache shader modules for reuse. Time to move to `slang` + private: + vk::ShaderModule CreateShader(std::string_view shaderFile); - eastl::array shaderStages = {{ - { - .stage = vk::ShaderStageFlagBits::eVertex, - .module = vertexShaderModule, - .pName = "main", - }, - { - .stage = vk::ShaderStageFlagBits::eFragment, - .module = fragmentShaderModule, - .pName = "main", - }, - }}; - - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = { - .setLayoutCount = 0, - .pSetLayouts = nullptr, - .pushConstantRangeCount = 0, - .pPushConstantRanges = nullptr, - }; - vk::PipelineLayout pipelineLayout; - vk::Result result = m_Device.m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout); - ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result); - m_Device.SetName(pipelineLayout, "Triangle Layout"); - - vk::VertexInputBindingDescription inputBindingDescription = Vertex::GetBinding(0); - auto inputAttributeDescription = Vertex::GetAttributes(0); - - vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = { - .vertexBindingDescriptionCount = 1, - .pVertexBindingDescriptions = &inputBindingDescription, - .vertexAttributeDescriptionCount = Cast(inputAttributeDescription.size()), - .pVertexAttributeDescriptions = inputAttributeDescription.data(), - }; - vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = { - .topology = vk::PrimitiveTopology::eTriangleList, - .primitiveRestartEnable = false, - }; - - vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { - .viewportCount = 1, - .scissorCount = 1, - }; - - vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = { - .depthClampEnable = false, - .rasterizerDiscardEnable = false, - .polygonMode = vk::PolygonMode::eFill, - .cullMode = vk::CullModeFlagBits::eNone, - .frontFace = vk::FrontFace::eCounterClockwise, - .depthBiasEnable = false, - .lineWidth = 1.0, - }; - vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = { - .rasterizationSamples = vk::SampleCountFlagBits::e1, - .sampleShadingEnable = false, - }; - vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = { - .depthTestEnable = false, - .depthWriteEnable = false, - }; - vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = { - .blendEnable = false, - .srcColorBlendFactor = vk::BlendFactor::eSrcColor, - .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor, - .colorBlendOp = vk::BlendOp::eAdd, - .srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha, - .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, - .alphaBlendOp = vk::BlendOp::eAdd, - .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | - vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, - }; - vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = { - .logicOpEnable = false, - .attachmentCount = 1, - .pAttachments = &colorBlendAttachmentState, - }; - - eastl::array dynamicStates = { - vk::DynamicState::eScissor, - vk::DynamicState::eViewport, - }; - - vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = { - .dynamicStateCount = Cast(dynamicStates.size()), - .pDynamicStates = dynamicStates.data(), - }; - - vk::PipelineRenderingCreateInfo renderingCreateInfo = { - .viewMask = 0, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &swapchain->m_Format, - }; - - vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { - .pNext = &renderingCreateInfo, - .stageCount = Cast(shaderStages.size()), - .pStages = shaderStages.data(), - .pVertexInputState = &vertexInputStateCreateInfo, - .pInputAssemblyState = &inputAssemblyStateCreateInfo, - .pViewportState = &viewportStateCreateInfo, - .pRasterizationState = &rasterizationStateCreateInfo, - .pMultisampleState = &multisampleStateCreateInfo, - .pDepthStencilState = &depthStencilStateCreateInfo, - .pColorBlendState = &colorBlendStateCreateInfo, - .pDynamicState = &dynamicStateCreateInfo, - .layout = pipelineLayout, - }; - vk::Pipeline pipeline; - result = m_Device.m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline); - ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result) - THEN_ABORT(result); - m_Device.SetName(pipeline, "Triangle Pipeline"); - - m_Device.m_Device.destroy(vertexShaderModule, nullptr); - m_Device.m_Device.destroy(fragmentShaderModule, nullptr); - - return {&m_Device, pipelineLayout, pipeline, {}}; - } - //*/ + public: + // Pipelines, unlike the other resources, are not ref-counted. + Pipeline CreatePipeline(const GraphicsPipelineCreateInfo &createInfo); // // Frames @@ -590,7 +525,7 @@ class Device final } [[nodiscard]] vk::Queue - GetQueue(u32 familyIndex, u32 queueIndex) const + GetQueue(const u32 familyIndex, const u32 queueIndex) const { return m_Device.GetQueue(familyIndex, queueIndex); } @@ -610,7 +545,7 @@ class Device final // Inner // ---------------------------------------------------------------------------------------------------- - [[nodiscard]] CoreDevice & + [[nodiscard]] ::Device & GetInner() { return m_Device; diff --git a/aster/include/aster/util/CMakeLists.txt b/aster/include/aster/util/CMakeLists.txt index fc5c8c0..5ce6a17 100644 --- a/aster/include/aster/util/CMakeLists.txt +++ b/aster/include/aster/util/CMakeLists.txt @@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13) target_sources(aster_core INTERFACE "logger.h" - "freelist.h") + "freelist.h" + "files.h") diff --git a/aster/include/aster/util/files.h b/aster/include/aster/util/files.h new file mode 100644 index 0000000..53e190d --- /dev/null +++ b/aster/include/aster/util/files.h @@ -0,0 +1,15 @@ +// ============================================= +// Aster: files.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "aster/core/constants.h" + +#include +#include + +eastl::vector ReadFile(std::string_view fileName); +eastl::vector ReadFileBytes(std::string_view fileName, bool errorOnFail = true); +bool WriteFileBytes(std::string_view fileName, eastl::span data); \ No newline at end of file diff --git a/aster/src/aster/systems/device.cpp b/aster/src/aster/systems/device.cpp index e24d80d..8cea14d 100644 --- a/aster/src/aster/systems/device.cpp +++ b/aster/src/aster/systems/device.cpp @@ -9,6 +9,8 @@ #include "core/window.h" #include "systems/resource.h" +#include "aster/util/files.h" + static constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer; @@ -416,6 +418,191 @@ systems::Device::CreateSampler(const SamplerCreateInfo &createInfo) return object; } +// Pipelines +// ---------------------------------------------------------------------------------------------------- + +Pipeline +systems::Device::CreatePipeline(const GraphicsPipelineCreateInfo &createInfo) +{ + auto findShader = [&shaderModules = createInfo.m_ShaderModules]( + GraphicsShaderModuleInfo::Type type) -> std::optional { + if (const auto res = + std::ranges::find_if(shaderModules, [type](const auto &v) { return v.m_Type == type; }); + res != std::ranges::end(shaderModules)) + { + return *res; + } + return std::nullopt; + }; + + auto vs = findShader(GraphicsShaderModuleInfo::Type::eVertex); + ERROR_IF(!vs, "Vertex Shader not found."); + GraphicsShaderModuleInfo vertexShader = *vs; + + auto fs = findShader(GraphicsShaderModuleInfo::Type::eFragment); + ERROR_IF(!fs, "Fragment Shader not found."); + GraphicsShaderModuleInfo fragmentShader = *fs; + + // Pipeline Setup + auto vertexShaderModule = CreateShader(vertexShader.m_ShaderFile); + auto fragmentShaderModule = CreateShader(fragmentShader.m_ShaderFile); + + eastl::array shaderStages = {{ + { + .stage = vk::ShaderStageFlagBits::eVertex, + .module = vertexShaderModule, + .pName = vertexShader.m_EntryPoint.data(), + }, + { + .stage = vk::ShaderStageFlagBits::eFragment, + .module = fragmentShaderModule, + .pName = fragmentShader.m_EntryPoint.data(), + }, + }}; + + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = { + .setLayoutCount = 0, + .pSetLayouts = nullptr, + .pushConstantRangeCount = 0, + .pPushConstantRanges = nullptr, + }; + vk::PipelineLayout pipelineLayout; + vk::Result result = m_Device.m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout); + ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result); + SetName(pipelineLayout, "Triangle Layout"); + + eastl::fixed_vector inputBindingDescriptions; + eastl::fixed_vector inputAttributeDescriptions; + u32 binding = 0; + for (auto vertexInput : createInfo.m_VertexInputs) + { + inputBindingDescriptions.push_back({ + .binding = binding, + .stride = vertexInput.m_Stride, + .inputRate = + vertexInput.m_IsPerInstance ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex, + }); + for (auto attrInput : vertexInput.m_Attribute) + { + inputAttributeDescriptions.push_back({ + .location = attrInput.m_Location, + .binding = binding, + .format = attrInput.GetFormat(), + .offset = attrInput.m_Offset, + }); + } + ++binding; + } + + vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = { + .vertexBindingDescriptionCount = Cast(inputBindingDescriptions.size()), + .pVertexBindingDescriptions = inputBindingDescriptions.data(), + .vertexAttributeDescriptionCount = Cast(inputAttributeDescriptions.size()), + .pVertexAttributeDescriptions = inputAttributeDescriptions.data(), + }; + vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = { + .topology = vk::PrimitiveTopology::eTriangleList, + .primitiveRestartEnable = false, + }; + + vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { + .viewportCount = 1, + .scissorCount = 1, + }; + + vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = { + .depthClampEnable = false, + .rasterizerDiscardEnable = false, + .polygonMode = vk::PolygonMode::eFill, + .cullMode = vk::CullModeFlagBits::eNone, + .frontFace = vk::FrontFace::eCounterClockwise, + .depthBiasEnable = false, + .lineWidth = 1.0, + }; + vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = { + .rasterizationSamples = vk::SampleCountFlagBits::e1, + .sampleShadingEnable = false, + }; + vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = { + .depthTestEnable = false, + .depthWriteEnable = false, + }; + vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = { + .blendEnable = false, + .srcColorBlendFactor = vk::BlendFactor::eSrcColor, + .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor, + .colorBlendOp = vk::BlendOp::eAdd, + .srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha, + .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, + .alphaBlendOp = vk::BlendOp::eAdd, + .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | + vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, + }; + vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = { + .logicOpEnable = false, + .attachmentCount = 1, + .pAttachments = &colorBlendAttachmentState, + }; + + eastl::array dynamicStates = { + vk::DynamicState::eScissor, + vk::DynamicState::eViewport, + }; + + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = { + .dynamicStateCount = Cast(dynamicStates.size()), + .pDynamicStates = dynamicStates.data(), + }; + + vk::PipelineRenderingCreateInfo renderingCreateInfo = { + .viewMask = 0, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &m_Swapchain.m_Format, + }; + + vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { + .pNext = &renderingCreateInfo, + .stageCount = Cast(shaderStages.size()), + .pStages = shaderStages.data(), + .pVertexInputState = &vertexInputStateCreateInfo, + .pInputAssemblyState = &inputAssemblyStateCreateInfo, + .pViewportState = &viewportStateCreateInfo, + .pRasterizationState = &rasterizationStateCreateInfo, + .pMultisampleState = &multisampleStateCreateInfo, + .pDepthStencilState = &depthStencilStateCreateInfo, + .pColorBlendState = &colorBlendStateCreateInfo, + .pDynamicState = &dynamicStateCreateInfo, + .layout = pipelineLayout, + }; + vk::Pipeline pipeline; + result = m_Device.m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline); + ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result) + THEN_ABORT(result); + SetName(pipeline, "Triangle Pipeline"); + + m_Device.m_Device.destroy(vertexShaderModule, nullptr); + m_Device.m_Device.destroy(fragmentShaderModule, nullptr); + + return {&m_Device, pipelineLayout, pipeline, {}}; +} + +vk::ShaderModule +systems::Device::CreateShader(std::string_view shaderFile) +{ + eastl::vector shaderCode = ReadFile(shaderFile); + + const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = { + .codeSize = shaderCode.size() * sizeof(u32), + .pCode = shaderCode.data(), + }; + vk::ShaderModule shaderModule; + + vk::Result result = m_Device.m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule); + ERROR_IF(Failed(result), "Shader {} could not be created. Cause: {}", shaderFile, result) + THEN_ABORT(result); + return shaderModule; +} + #pragma endregion QueueAllocation @@ -637,11 +824,11 @@ systems::Frame::CreateGraphicsContext() } else { - const vk::CommandBufferAllocateInfo allocateInfo{ - .commandPool = m_Pool, - .level = vk::CommandBufferLevel::ePrimary, - .commandBufferCount = 1, - }; + const vk::CommandBufferAllocateInfo allocateInfo{ + .commandPool = m_Pool, + .level = vk::CommandBufferLevel::ePrimary, + .commandBufferCount = 1, + }; AbortIfFailedMV(m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &cmd), "Command buffer {} alloc failed.", m_FrameIdx); m_CommandBuffers.push_back(cmd); @@ -695,9 +882,9 @@ systems::GraphicsContext::BindVertexBuffer(const Ref &vertexBuffer } void -systems::GraphicsContext::BindPipeline(vk::Pipeline pipeline) +systems::GraphicsContext::BindPipeline(const Pipeline &pipeline) { - m_Cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); + m_Cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline); } void diff --git a/aster/src/aster/util/CMakeLists.txt b/aster/src/aster/util/CMakeLists.txt index 6803276..2bcdad0 100644 --- a/aster/src/aster/util/CMakeLists.txt +++ b/aster/src/aster/util/CMakeLists.txt @@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 3.13) -target_sources(aster_core PRIVATE "logger.cpp" ) +target_sources(aster_core PRIVATE "logger.cpp" "files.cpp") diff --git a/aster/src/aster/util/files.cpp b/aster/src/aster/util/files.cpp new file mode 100644 index 0000000..44490ec --- /dev/null +++ b/aster/src/aster/util/files.cpp @@ -0,0 +1,79 @@ +// ============================================= +// Aster: files.cpp +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#include "aster/util/files.h" + +eastl::vector +ReadFile(std::string_view fileName) +{ + FILE *filePtr = fopen(fileName.data(), "rb"); + + if (!filePtr) + { + ERROR("Invalid read of {}", fileName) THEN_ABORT(-1); + } + + eastl::vector outputVec; + eastl::array buffer{}; + usize totalRead = 0; + usize readCount; + do + { + readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr); + const auto nextSize = totalRead + readCount; + outputVec.resize(nextSize); + memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); + totalRead = nextSize; + } while (readCount == buffer.size()); + + return outputVec; +} + +eastl::vector +ReadFileBytes(std::string_view fileName, bool errorOnFail) +{ + FILE *filePtr = fopen(fileName.data(), "rb"); + + if (!filePtr) + { + ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno); + return {}; + } + + eastl::vector outputVec; + eastl::array buffer{}; + usize totalRead = 0; + usize readCount; + do + { + readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr); + const auto nextSize = totalRead + readCount; + outputVec.resize(nextSize); + memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); + totalRead = nextSize; + } while (readCount == buffer.size()); + + (void)fclose(filePtr); + + return outputVec; +} + +bool +WriteFileBytes(std::string_view fileName, const eastl::span data) +{ + FILE *filePtr = fopen(fileName.data(), "wb"); + + if (!filePtr) + { + ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno); + return false; + } + + const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr); + + (void)fclose(filePtr); + + return written == data.size(); +} \ No newline at end of file diff --git a/samples/00_util/helpers.cpp b/samples/00_util/helpers.cpp index b2ba5e8..244d983 100644 --- a/samples/00_util/helpers.cpp +++ b/samples/00_util/helpers.cpp @@ -62,76 +62,3 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice) ERROR("No suitable queue family on the GPU.") THEN_ABORT(vk::Result::eErrorUnknown); } - -eastl::vector -ReadFile(cstr fileName) -{ - FILE *filePtr = fopen(fileName, "rb"); - - if (!filePtr) - { - ERROR("Invalid read of {}", fileName) THEN_ABORT(-1); - } - - eastl::vector outputVec; - eastl::array buffer{}; - usize totalRead = 0; - usize readCount; - do - { - readCount = fread(buffer.data(), sizeof(u32), buffer.size(), filePtr); - const auto nextSize = totalRead + readCount; - outputVec.resize(nextSize); - memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); - totalRead = nextSize; - } while (readCount == buffer.size()); - - return outputVec; -} - -eastl::vector -ReadFileBytes(cstr fileName, bool errorOnFail) -{ - FILE *filePtr = fopen(fileName, "rb"); - - if (!filePtr) - { - ERROR_IF(errorOnFail, "Invalid open (r) of {}. Cause: {}", fileName, errno); - return {}; - } - - eastl::vector outputVec; - eastl::array buffer{}; - usize totalRead = 0; - usize readCount; - do - { - readCount = fread(buffer.data(), sizeof(u8), buffer.size(), filePtr); - const auto nextSize = totalRead + readCount; - outputVec.resize(nextSize); - memcpy(outputVec.data() + totalRead, buffer.data(), readCount * sizeof *buffer.data()); - totalRead = nextSize; - } while (readCount == buffer.size()); - - (void)fclose(filePtr); - - return outputVec; -} - -bool -WriteFileBytes(cstr fileName, eastl::span data) -{ - FILE *filePtr = fopen(fileName, "wb"); - - if (!filePtr) - { - ERROR("Invalid open (w) of {}. Cause: {}", fileName, errno); - return false; - } - - const usize written = fwrite(data.data(), sizeof(u8), data.size(), filePtr); - - (void)fclose(filePtr); - - return written == data.size(); -} \ No newline at end of file diff --git a/samples/00_util/helpers.h b/samples/00_util/helpers.h index 4dd8639..3471a02 100644 --- a/samples/00_util/helpers.h +++ b/samples/00_util/helpers.h @@ -18,9 +18,6 @@ class PhysicalDevices; PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices); QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice); -eastl::vector ReadFile(cstr fileName); -eastl::vector ReadFileBytes(cstr fileName, bool errorOnFail = true); -bool WriteFileBytes(cstr fileName, eastl::span data); template using StackString = eastl::fixed_string; diff --git a/samples/01_triangle/triangle.cpp b/samples/01_triangle/triangle.cpp index 8c45b15..a4f5dfc 100644 --- a/samples/01_triangle/triangle.cpp +++ b/samples/01_triangle/triangle.cpp @@ -13,7 +13,9 @@ #include "aster/core/swapchain.h" #include "aster/core/window.h" +#include "aster/core/pipeline.h" #include "aster/systems/device.h" +#include "aster/util/files.h" #include "helpers.h" #include @@ -21,9 +23,6 @@ constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vert.glsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/triangle.frag.glsl.spv"; -vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); -Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain); - struct Vertex { vec3 m_Position; @@ -69,7 +68,37 @@ main(int, char **) .m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true}}, }}; - Pipeline pipeline = CreatePipeline(&device.m_Device, &device.m_Swapchain); + Pipeline pipeline = device.CreatePipeline({ + .m_VertexInputs = {{ + .m_Attribute = + { + { + .m_Location = 0, + .m_Offset = offsetof(Vertex, m_Position), + .m_Format = systems::AttributeInfo::Format::eFloat32X3, + }, + { + .m_Location = 1, + .m_Offset = offsetof(Vertex, m_Color), + .m_Format = systems::AttributeInfo::Format::eFloat32X3, + }, + }, + .m_Stride = sizeof(Vertex), + }}, + .m_ShaderModules = + { + { + .m_ShaderFile = VERTEX_SHADER_FILE, + .m_EntryPoint = "main", + .m_Type = systems::GraphicsShaderModuleInfo::Type::eVertex, + }, + { + .m_ShaderFile = FRAGMENT_SHADER_FILE, + .m_EntryPoint = "main", + .m_Type = systems::GraphicsShaderModuleInfo::Type::eFragment, + }, + }, + }); // eastl::array vertices{}; eastl::array vertices = { @@ -168,7 +197,7 @@ main(int, char **) context.BeginRendering(renderingInfo); context.SetViewport(viewport); - context.BindPipeline(pipeline.m_Pipeline); + context.BindPipeline(pipeline); context.BindVertexBuffer(vbo); context.Draw(3); @@ -187,146 +216,3 @@ main(int, char **) return 0; } - -Pipeline -CreatePipeline(const Device *device, const Swapchain *swapchain) -{ - // Pipeline Setup - auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE); - auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE); - - eastl::array shaderStages = {{ - { - .stage = vk::ShaderStageFlagBits::eVertex, - .module = vertexShaderModule, - .pName = "main", - }, - { - .stage = vk::ShaderStageFlagBits::eFragment, - .module = fragmentShaderModule, - .pName = "main", - }, - }}; - - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = { - .setLayoutCount = 0, - .pSetLayouts = nullptr, - .pushConstantRangeCount = 0, - .pPushConstantRanges = nullptr, - }; - vk::PipelineLayout pipelineLayout; - vk::Result result = device->m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout); - ERROR_IF(Failed(result), "Could not create a pipeline layout. Cause: {}", result) THEN_ABORT(result); - device->SetName(pipelineLayout, "Triangle Layout"); - - vk::VertexInputBindingDescription inputBindingDescription = Vertex::GetBinding(0); - auto inputAttributeDescription = Vertex::GetAttributes(0); - - vk::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = { - .vertexBindingDescriptionCount = 1, - .pVertexBindingDescriptions = &inputBindingDescription, - .vertexAttributeDescriptionCount = Cast(inputAttributeDescription.size()), - .pVertexAttributeDescriptions = inputAttributeDescription.data(), - }; - vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = { - .topology = vk::PrimitiveTopology::eTriangleList, - .primitiveRestartEnable = false, - }; - - vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { - .viewportCount = 1, - .scissorCount = 1, - }; - - vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = { - .depthClampEnable = false, - .rasterizerDiscardEnable = false, - .polygonMode = vk::PolygonMode::eFill, - .cullMode = vk::CullModeFlagBits::eNone, - .frontFace = vk::FrontFace::eCounterClockwise, - .depthBiasEnable = false, - .lineWidth = 1.0, - }; - vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = { - .rasterizationSamples = vk::SampleCountFlagBits::e1, - .sampleShadingEnable = false, - }; - vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = { - .depthTestEnable = false, - .depthWriteEnable = false, - }; - vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = { - .blendEnable = false, - .srcColorBlendFactor = vk::BlendFactor::eSrcColor, - .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcColor, - .colorBlendOp = vk::BlendOp::eAdd, - .srcAlphaBlendFactor = vk::BlendFactor::eSrcAlpha, - .dstAlphaBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, - .alphaBlendOp = vk::BlendOp::eAdd, - .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | - vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, - }; - vk::PipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = { - .logicOpEnable = false, - .attachmentCount = 1, - .pAttachments = &colorBlendAttachmentState, - }; - - eastl::array dynamicStates = { - vk::DynamicState::eScissor, - vk::DynamicState::eViewport, - }; - - vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = { - .dynamicStateCount = Cast(dynamicStates.size()), - .pDynamicStates = dynamicStates.data(), - }; - - vk::PipelineRenderingCreateInfo renderingCreateInfo = { - .viewMask = 0, - .colorAttachmentCount = 1, - .pColorAttachmentFormats = &swapchain->m_Format, - }; - - vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { - .pNext = &renderingCreateInfo, - .stageCount = Cast(shaderStages.size()), - .pStages = shaderStages.data(), - .pVertexInputState = &vertexInputStateCreateInfo, - .pInputAssemblyState = &inputAssemblyStateCreateInfo, - .pViewportState = &viewportStateCreateInfo, - .pRasterizationState = &rasterizationStateCreateInfo, - .pMultisampleState = &multisampleStateCreateInfo, - .pDepthStencilState = &depthStencilStateCreateInfo, - .pColorBlendState = &colorBlendStateCreateInfo, - .pDynamicState = &dynamicStateCreateInfo, - .layout = pipelineLayout, - }; - vk::Pipeline pipeline; - result = device->m_Device.createGraphicsPipelines(nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline); - ERROR_IF(Failed(result), "Could not create a graphics pipeline. Cause: {}", result) - THEN_ABORT(result); - device->SetName(pipeline, "Triangle Pipeline"); - - device->m_Device.destroy(vertexShaderModule, nullptr); - device->m_Device.destroy(fragmentShaderModule, nullptr); - - return {device, pipelineLayout, pipeline, {}}; -} - -vk::ShaderModule -CreateShader(const Device *device, cstr shaderFile) -{ - eastl::vector shaderCode = ReadFile(shaderFile); - - const vk::ShaderModuleCreateInfo shaderModuleCreateInfo = { - .codeSize = shaderCode.size() * sizeof(u32), - .pCode = shaderCode.data(), - }; - vk::ShaderModule shaderModule; - - vk::Result result = device->m_Device.createShaderModule(&shaderModuleCreateInfo, nullptr, &shaderModule); - ERROR_IF(Failed(result), "Shader {} could not be created. Cause: {}", shaderFile, result) - THEN_ABORT(result); - return shaderModule; -}