Added Pipeline creation into the Device.
This commit is contained in:
parent
2facb3e6c1
commit
7507394af9
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <EASTL/hash_map.h>
|
||||
#include <EASTL/optional.h>
|
||||
|
|
@ -25,7 +25,6 @@
|
|||
constexpr static u32 MAX_FRAMES_IN_FLIGHT = 3;
|
||||
|
||||
struct Window;
|
||||
using CoreDevice = Device;
|
||||
|
||||
template <>
|
||||
struct eastl::hash<vk::SamplerCreateInfo>
|
||||
|
|
@ -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<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
|
||||
|
||||
|
|
@ -291,7 +344,7 @@ class GraphicsContext : public Context
|
|||
public:
|
||||
DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport);
|
||||
void BindVertexBuffer(const Ref<VertexBuffer> &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<vk::CommandBuffer> 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<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 = 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, {}};
|
||||
}
|
||||
//*/
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ cmake_minimum_required(VERSION 3.13)
|
|||
target_sources(aster_core
|
||||
INTERFACE
|
||||
"logger.h"
|
||||
"freelist.h")
|
||||
"freelist.h"
|
||||
"files.h")
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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<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
|
||||
|
||||
QueueAllocation
|
||||
|
|
@ -695,9 +882,9 @@ systems::GraphicsContext::BindVertexBuffer(const Ref<VertexBuffer> &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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -62,76 +62,3 @@ FindAppropriateQueueAllocation(const PhysicalDevice *physicalDevice)
|
|||
ERROR("No suitable queue family on the GPU.")
|
||||
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();
|
||||
}
|
||||
|
|
@ -18,9 +18,6 @@ class PhysicalDevices;
|
|||
|
||||
PhysicalDevice FindSuitableDevice(const PhysicalDevices &physicalDevices);
|
||||
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>
|
||||
using StackString = eastl::fixed_string<char, TSize, false>;
|
||||
|
|
|
|||
|
|
@ -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 <EASTL/array.h>
|
||||
|
|
@ -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<Vertex, 3> 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<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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue