Added Pipeline creation into the Device.

This commit is contained in:
Anish Bhobe 2025-05-03 13:44:47 +02:00
parent 2facb3e6c1
commit 7507394af9
10 changed files with 393 additions and 365 deletions

View File

@ -16,6 +16,7 @@
#define VULKAN_HPP_DISABLE_ENHANCED_MODE 1 #define VULKAN_HPP_DISABLE_ENHANCED_MODE 1
#define VULKAN_HPP_NO_EXCEPTIONS 1 #define VULKAN_HPP_NO_EXCEPTIONS 1
#define VULKAN_HPP_NO_SMART_HANDLE 1 #define VULKAN_HPP_NO_SMART_HANDLE 1
#define VULKAN_HPP_NO_STRUCT_SETTERS 1
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1

View File

@ -12,9 +12,9 @@
#include "aster/core/image_view.h" #include "aster/core/image_view.h"
#include "aster/core/instance.h" #include "aster/core/instance.h"
#include "aster/core/physical_device.h" #include "aster/core/physical_device.h"
#include "aster/core/pipeline.h"
#include "aster/core/sampler.h" #include "aster/core/sampler.h"
#include "aster/core/swapchain.h" #include "aster/core/swapchain.h"
#include "aster/core/pipeline.h"
#include <EASTL/hash_map.h> #include <EASTL/hash_map.h>
#include <EASTL/optional.h> #include <EASTL/optional.h>
@ -25,7 +25,6 @@
constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3; constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3;
struct Window; struct Window;
using CoreDevice = Device;
template <> template <>
struct eastl::hash<vk::SamplerCreateInfo> struct eastl::hash<vk::SamplerCreateInfo>
@ -226,7 +225,61 @@ struct SamplerCreateInfo
#pragma region Pipeline #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<AttributeInfo> 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<VertexInput, 4, false> m_VertexInputs;
eastl::fixed_vector<GraphicsShaderModuleInfo, 4, false> m_ShaderModules;
};
#pragma endregion #pragma endregion
@ -291,7 +344,7 @@ class GraphicsContext : public Context
public: public:
DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport); DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport);
void BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer); void BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer);
DEPRECATE_RAW_CALLS void BindPipeline(vk::Pipeline pipeline); void BindPipeline(const Pipeline &pipeline);
void Draw(u32 vertexCount); void Draw(u32 vertexCount);
void DrawIndexed(u32 indexCount); void DrawIndexed(u32 indexCount);
@ -311,8 +364,9 @@ struct Frame
vk::Semaphore m_RenderFinishSem; vk::Semaphore m_RenderFinishSem;
u32 m_FrameIdx; u32 m_FrameIdx;
eastl::vector<vk::CommandBuffer> m_CommandBuffers;
// Transient // Transient
u32 m_ImageIdx;
vk::Image m_SwapchainImage; vk::Image m_SwapchainImage;
vk::ImageView m_SwapchainImageView; vk::ImageView m_SwapchainImageView;
u32 m_ImageIdx; u32 m_ImageIdx;
@ -428,132 +482,13 @@ class Device final
// Pipeline // Pipeline
// ---------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------
/* // TODO: Cache shader modules for reuse. Time to move to `slang`
Pipeline CreatePipeline() private:
{ vk::ShaderModule CreateShader(std::string_view shaderFile);
// Pipeline Setup
auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE);
auto fragmentShaderModule = CreateShader(device, FRAGMENT_SHADER_FILE);
eastl::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {{ public:
{ // Pipelines, unlike the other resources, are not ref-counted.
.stage = vk::ShaderStageFlagBits::eVertex, Pipeline CreatePipeline(const GraphicsPipelineCreateInfo &createInfo);
.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<u32>(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<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain->m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(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, {}};
}
//*/
// //
// Frames // Frames
@ -590,7 +525,7 @@ class Device final
} }
[[nodiscard]] vk::Queue [[nodiscard]] vk::Queue
GetQueue(u32 familyIndex, u32 queueIndex) const GetQueue(const u32 familyIndex, const u32 queueIndex) const
{ {
return m_Device.GetQueue(familyIndex, queueIndex); return m_Device.GetQueue(familyIndex, queueIndex);
} }
@ -610,7 +545,7 @@ class Device final
// Inner // Inner
// ---------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------
[[nodiscard]] CoreDevice & [[nodiscard]] ::Device &
GetInner() GetInner()
{ {
return m_Device; return m_Device;

View File

@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
target_sources(aster_core target_sources(aster_core
INTERFACE INTERFACE
"logger.h" "logger.h"
"freelist.h") "freelist.h"
"files.h")

View File

@ -0,0 +1,15 @@
// =============================================
// Aster: files.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "aster/core/constants.h"
#include <EASTL/span.h>
#include <EASTL/vector.h>
eastl::vector<u32> ReadFile(std::string_view fileName);
eastl::vector<u8> ReadFileBytes(std::string_view fileName, bool errorOnFail = true);
bool WriteFileBytes(std::string_view fileName, eastl::span<u8> data);

View File

@ -9,6 +9,8 @@
#include "core/window.h" #include "core/window.h"
#include "systems/resource.h" #include "systems/resource.h"
#include "aster/util/files.h"
static constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT = static constexpr QueueSupportFlags REQUIRED_QUEUE_SUPPORT =
QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute | QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::eCompute |
QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer; QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer;
@ -416,6 +418,191 @@ systems::Device::CreateSampler(const SamplerCreateInfo &createInfo)
return object; return object;
} }
// Pipelines
// ----------------------------------------------------------------------------------------------------
Pipeline
systems::Device::CreatePipeline(const GraphicsPipelineCreateInfo &createInfo)
{
auto findShader = [&shaderModules = createInfo.m_ShaderModules](
GraphicsShaderModuleInfo::Type type) -> std::optional<GraphicsShaderModuleInfo> {
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<vk::PipelineShaderStageCreateInfo, 2> 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<vk::VertexInputBindingDescription, 4, false> inputBindingDescriptions;
eastl::fixed_vector<vk::VertexInputAttributeDescription, 4, false> 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<u32>(inputBindingDescriptions.size()),
.pVertexBindingDescriptions = inputBindingDescriptions.data(),
.vertexAttributeDescriptionCount = Cast<u32>(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<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &m_Swapchain.m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(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<u32> 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 #pragma endregion
QueueAllocation QueueAllocation
@ -695,9 +882,9 @@ systems::GraphicsContext::BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer
} }
void 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 void

View File

@ -2,4 +2,4 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
target_sources(aster_core PRIVATE "logger.cpp" ) target_sources(aster_core PRIVATE "logger.cpp" "files.cpp")

View File

@ -0,0 +1,79 @@
// =============================================
// Aster: files.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "aster/util/files.h"
eastl::vector<u32>
ReadFile(std::string_view fileName)
{
FILE *filePtr = fopen(fileName.data(), "rb");
if (!filePtr)
{
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
}
eastl::vector<u32> outputVec;
eastl::array<u32, 1024> 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<u8>
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<u8> outputVec;
eastl::array<u8, 4096> 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<u8> 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();
}

View File

@ -62,76 +62,3 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
ERROR("No suitable queue family on the GPU.") ERROR("No suitable queue family on the GPU.")
THEN_ABORT(vk::Result::eErrorUnknown); THEN_ABORT(vk::Result::eErrorUnknown);
} }
eastl::vector<u32>
ReadFile(cstr fileName)
{
FILE *filePtr = fopen(fileName, "rb");
if (!filePtr)
{
ERROR("Invalid read of {}", fileName) THEN_ABORT(-1);
}
eastl::vector<u32> outputVec;
eastl::array<u32, 1024> 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<u8>
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<u8> outputVec;
eastl::array<u8, 4096> 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<u8> 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();
}

View File

@ -18,9 +18,6 @@ class PhysicalDevices;
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices); PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice); QueueAllocation FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice);
eastl::vector<u32> ReadFile(cstr fileName);
eastl::vector<u8> ReadFileBytes(cstr fileName, bool errorOnFail = true);
bool WriteFileBytes(cstr fileName, eastl::span<u8> data);
template <usize TSize> template <usize TSize>
using StackString = eastl::fixed_string<char, TSize, false>; using StackString = eastl::fixed_string<char, TSize, false>;

View File

@ -13,7 +13,9 @@
#include "aster/core/swapchain.h" #include "aster/core/swapchain.h"
#include "aster/core/window.h" #include "aster/core/window.h"
#include "aster/core/pipeline.h"
#include "aster/systems/device.h" #include "aster/systems/device.h"
#include "aster/util/files.h"
#include "helpers.h" #include "helpers.h"
#include <EASTL/array.h> #include <EASTL/array.h>
@ -21,9 +23,6 @@
constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vert.glsl.spv"; constexpr auto VERTEX_SHADER_FILE = "shader/triangle.vert.glsl.spv";
constexpr auto FRAGMENT_SHADER_FILE = "shader/triangle.frag.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 struct Vertex
{ {
vec3 m_Position; vec3 m_Position;
@ -69,7 +68,37 @@ main(int, char **)
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true}}, .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<Vertex, 3> vertices{}; // eastl::array<Vertex, 3> vertices{};
eastl::array vertices = { eastl::array vertices = {
@ -168,7 +197,7 @@ main(int, char **)
context.BeginRendering(renderingInfo); context.BeginRendering(renderingInfo);
context.SetViewport(viewport); context.SetViewport(viewport);
context.BindPipeline(pipeline.m_Pipeline); context.BindPipeline(pipeline);
context.BindVertexBuffer(vbo); context.BindVertexBuffer(vbo);
context.Draw(3); context.Draw(3);
@ -187,146 +216,3 @@ main(int, char **)
return 0; 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<vk::PipelineShaderStageCreateInfo, 2> 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<u32>(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<u32>(dynamicStates.size()),
.pDynamicStates = dynamicStates.data(),
};
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.viewMask = 0,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &swapchain->m_Format,
};
vk::GraphicsPipelineCreateInfo pipelineCreateInfo = {
.pNext = &renderingCreateInfo,
.stageCount = Cast<u32>(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<u32> 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;
}