project-aster/samples/01_triangle/triangle.cpp

196 lines
6.3 KiB
C++

// =============================================
// Aster: triangle.cpp
// Copyright (c) 2020-2025 Anish Bhobe
// =============================================
#include "aster/aster.h"
#include "aster/core/buffer.h"
#include "aster/core/constants.h"
#include "aster/core/instance.h"
#include "aster/core/physical_device.h"
#include "aster/core/pipeline.h"
#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>
constexpr auto SHADER_MODULE = "triangle.slang";
struct Vertex
{
vec3 m_Position;
vec3 m_Color;
static eastl::vector<systems::AttributeInfo>
GetAttributes()
{
return {
{
.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,
},
};
}
};
int
main(int, char **)
{
MIN_LOG_LEVEL(Logger::LogType::eInfo);
Window window = {"Triangle (Aster)", {640, 480}};
systems::Device device{{
.m_Window = window,
.m_Features = {.m_Vulkan12Features = {.bufferDeviceAddress = true},
.m_Vulkan13Features = {.synchronization2 = true, .dynamicRendering = true}},
.m_AppName = "Triangle",
.m_ShaderSearchPaths = {"shader/"},
.m_Name = "Primary",
}};
Pipeline pipeline;
auto pipelineError = device.CreatePipeline(
pipeline, {
.m_VertexInputs = {{
.m_Attribute = Vertex::GetAttributes(),
.m_Stride = sizeof(Vertex),
}},
.m_Shaders = {{
.m_ShaderFile = SHADER_MODULE,
.m_EntryPoints = {"vsmain", "fsmain"},
}},
});
ERROR_IF(pipelineError, "Error creating pipeline. Cause: {}", pipelineError.What());
// eastl::array<Vertex, 3> vertices{};
eastl::array vertices = {
Vertex{.m_Position = {-0.5f, -0.5f, 0.0f}, .m_Color = {1.0f, 0.0f, 0.0f}},
Vertex{.m_Position = {0.5f, -0.5f, 0.0f}, .m_Color = {0.0f, 1.0f, 0.0f}},
Vertex{.m_Position = {0.0f, 0.5f, 0.0f}, .m_Color = {0.0f, 0.0f, 1.0f}},
};
auto vbo = device.CreateVertexBuffer(vertices.size() * sizeof vertices[0], "VBO");
vbo->Write(0, vertices.size() * sizeof vertices[0], vertices.data());
// Persistent variables
vk::ImageSubresourceRange subresourceRange = {
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
vk::ImageMemoryBarrier2 topOfThePipeBarrier = {
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
.srcAccessMask = vk::AccessFlagBits2::eNone,
.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eColorAttachmentOptimal,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo topOfThePipeDependency = {
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &topOfThePipeBarrier,
};
vk::ImageMemoryBarrier2 renderToPresentBarrier = {
.srcStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
.srcAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
.dstStageMask = vk::PipelineStageFlagBits2::eBottomOfPipe,
.dstAccessMask = vk::AccessFlagBits2::eNone,
.oldLayout = vk::ImageLayout::eColorAttachmentOptimal,
.newLayout = vk::ImageLayout::ePresentSrcKHR,
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
.subresourceRange = subresourceRange,
};
vk::DependencyInfo renderToPresentDependency = {
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &renderToPresentBarrier,
};
INFO("Starting loop");
while (window.Poll())
{
systems::Frame &currentFrame = device.GetNextFrame();
Size2D swapchainSize = currentFrame.m_SwapchainSize;
vk::Viewport viewport = {
.x = 0,
.y = static_cast<f32>(swapchainSize.m_Height),
.width = static_cast<f32>(swapchainSize.m_Width),
.height = -static_cast<f32>(swapchainSize.m_Height),
.minDepth = 0.0,
.maxDepth = 1.0,
};
vk::Rect2D scissor = {
.offset = {0, 0},
.extent = static_cast<vk::Extent2D>(swapchainSize),
};
auto context = currentFrame.CreateGraphicsContext();
topOfThePipeBarrier.image = currentFrame.m_SwapchainImage;
renderToPresentBarrier.image = currentFrame.m_SwapchainImage;
context.Begin();
context.Dependency(topOfThePipeDependency);
// Render
vk::RenderingAttachmentInfo attachmentInfo = {
.imageView = currentFrame.m_SwapchainImageView,
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
.resolveMode = vk::ResolveModeFlagBits::eNone,
.loadOp = vk::AttachmentLoadOp::eClear,
.storeOp = vk::AttachmentStoreOp::eStore,
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 0.0f},
};
vk::RenderingInfo renderingInfo = {
.renderArea = scissor,
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo,
};
context.BeginRendering(renderingInfo);
context.SetViewport(viewport);
context.BindPipeline(pipeline);
context.BindVertexBuffer(vbo);
context.Draw(3);
context.EndRendering();
context.Dependency(renderToPresentDependency);
context.End();
device.Submit(currentFrame, context);
device.Present(currentFrame);
}
device.WaitIdle();
return 0;
}