From d6fe7163228c370fc6b4ec1e67c2ee44783f9db1 Mon Sep 17 00:00:00 2001 From: Anish Bhobe Date: Tue, 2 Jul 2024 09:06:08 +0200 Subject: [PATCH] [WIP] Moving to example 2. --- aster/CMakeLists.txt | 10 +- aster/buffer.cpp | 36 +++ aster/buffer.h | 22 ++ samples/01_triangle/triangle.cpp | 5 +- samples/02_box/CMakeLists.txt | 13 + samples/02_box/box.cpp | 455 ++++++++++++++++++++++++++++++ samples/02_box/camera.cpp | 16 ++ samples/02_box/camera.h | 14 + samples/02_box/shader/box.ps.hlsl | 9 + samples/02_box/shader/box.vs.hlsl | 28 ++ samples/CMakeLists.txt | 3 +- 11 files changed, 603 insertions(+), 8 deletions(-) create mode 100644 aster/buffer.cpp create mode 100644 aster/buffer.h create mode 100644 samples/02_box/CMakeLists.txt create mode 100644 samples/02_box/box.cpp create mode 100644 samples/02_box/camera.cpp create mode 100644 samples/02_box/camera.h create mode 100644 samples/02_box/shader/box.ps.hlsl create mode 100644 samples/02_box/shader/box.vs.hlsl diff --git a/aster/CMakeLists.txt b/aster/CMakeLists.txt index 9522cf3..bc0f73c 100644 --- a/aster/CMakeLists.txt +++ b/aster/CMakeLists.txt @@ -20,8 +20,9 @@ set(HEADER_FILES physical_device.h device.h swapchain.h - "pipeline.h" - queue_allocation.h) + pipeline.h + queue_allocation.h + buffer.h) set(SOURCE_FILES logger.cpp @@ -31,7 +32,8 @@ set(SOURCE_FILES physical_device.cpp device.cpp swapchain.cpp - pipeline.cpp) + pipeline.cpp + buffer.cpp) add_library(aster_core STATIC ${SOURCE_FILES} ${HEADER_FILES}) set_property(TARGET aster_core PROPERTY CXX_STANDARD 20) @@ -40,7 +42,7 @@ target_precompile_headers(aster_core PUBLIC global.h) target_include_directories(aster_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(aster_core PUBLIC glm::glm-header-only) +target_link_libraries(aster_core PUBLIC glm::glm) target_link_libraries(aster_core PRIVATE glfw) target_include_directories(aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS}) target_link_libraries(aster_core PRIVATE fmt::fmt) diff --git a/aster/buffer.cpp b/aster/buffer.cpp new file mode 100644 index 0000000..5925af6 --- /dev/null +++ b/aster/buffer.cpp @@ -0,0 +1,36 @@ +// ============================================= +// Aster: buffer.cpp +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#include "buffer.h" + +#include "device.h" +Buffer::Buffer(const Device *device, const usize size, const vk::BufferUsageFlags usage, NameString &&name) + : m_Device(device) + , m_Allocation(nullptr) + , m_Size(0) + , m_Name(std::move(name)) +{ + const VkBufferCreateInfo bufferCreateInfo = vk::BufferCreateInfo{ + .size = size, + .usage = usage, + .sharingMode = vk::SharingMode::eExclusive, + }; + + constexpr VmaAllocationCreateInfo allocationCreateInfo = {.usage = VMA_MEMORY_USAGE_AUTO}; + + VkBuffer buffer; + vk::Result result = Cast(vmaCreateBuffer(m_Device->m_Allocator, &bufferCreateInfo, + &allocationCreateInfo, &buffer, &m_Allocation, nullptr)); + ERROR_IF(Failed(result), "Could not create buffer. Cause: {}", result) THEN_ABORT(result); + + m_Buffer = buffer; + + m_Device->SetName(m_Buffer, m_Name.c_str()); +} + +Buffer::~Buffer() +{ + vmaDestroyBuffer(m_Device->m_Allocator, m_Buffer, m_Allocation); +} \ No newline at end of file diff --git a/aster/buffer.h b/aster/buffer.h new file mode 100644 index 0000000..45de164 --- /dev/null +++ b/aster/buffer.h @@ -0,0 +1,22 @@ +// ============================================= +// Aster: buffer.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "global.h" + +struct Device; + +struct Buffer +{ + const Device *m_Device{}; + vk::Buffer m_Buffer{}; + VmaAllocation m_Allocation{}; + usize m_Size{}; + NameString m_Name; + + Buffer(const Device *device, usize size, vk::BufferUsageFlags usage, NameString &&name); + ~Buffer(); +}; \ No newline at end of file diff --git a/samples/01_triangle/triangle.cpp b/samples/01_triangle/triangle.cpp index f0c0992..5aa3b65 100644 --- a/samples/01_triangle/triangle.cpp +++ b/samples/01_triangle/triangle.cpp @@ -6,12 +6,11 @@ #include "constants.h" #include "context.h" #include "device.h" -#include "physical_device.h" -#include "window.h" - #include "global.h" +#include "physical_device.h" #include "pipeline.h" #include "swapchain.h" +#include "window.h" #include "helpers.h" diff --git a/samples/02_box/CMakeLists.txt b/samples/02_box/CMakeLists.txt new file mode 100644 index 0000000..9db70b7 --- /dev/null +++ b/samples/02_box/CMakeLists.txt @@ -0,0 +1,13 @@ +# CMakeList.txt ; CMake project for box + +cmake_minimum_required(VERSION 3.13) + +add_executable(box + box.cpp + camera.h + camera.cpp) +add_shader(box shader/box.vs.hlsl) +add_shader(box shader/box.ps.hlsl) + +target_link_libraries(box PRIVATE aster_core) +target_link_libraries(box PRIVATE util_helper) diff --git a/samples/02_box/box.cpp b/samples/02_box/box.cpp new file mode 100644 index 0000000..5eab4e1 --- /dev/null +++ b/samples/02_box/box.cpp @@ -0,0 +1,455 @@ +// ============================================= +// Aster: box.cpp +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#include "../../aster/buffer.h" +#include "../../aster/constants.h" +#include "../../aster/context.h" +#include "../../aster/device.h" +#include "../../aster/physical_device.h" +#include "../../aster/window.h" +#include "camera.h" + +#include "../../aster/global.h" +#include "../../aster/pipeline.h" +#include "../../aster/swapchain.h" + +#include "helpers.h" + +#include + +constexpr u32 MAX_FRAMES_IN_FLIGHT = 3; +constexpr auto VERTEX_SHADER_FILE = "shader/box.vs.hlsl.spv"; +constexpr auto FRAGMENT_SHADER_FILE = "shader/box.ps.hlsl.spv"; + +vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); +Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain); + +struct Frame +{ + const Device *m_Device; + vk::CommandPool m_Pool; + vk::Fence m_FrameAvailableFence; + vk::Semaphore m_ImageAcquireSem; + vk::Semaphore m_RenderFinishSem; + + Frame(const Device *device, u32 queueFamilyIndex, u32 frameCount); + ~Frame(); + + [[nodiscard]] vk::CommandBuffer AllocateCommandBuffer() const; +}; + +int +main(int, char **) +{ + MIN_LOG_LEVEL(Logger::LogType::eInfo); + + Context context = {"Triangle", VERSION}; + Window window = {"Triangle (Aster)", &context, {640, 480}}; + + PhysicalDevices physicalDevices = {&window, &context}; + PhysicalDevice deviceToUse = FindSuitableDevice(physicalDevices); + + INFO("Using {} as the primary device.", deviceToUse.m_DeviceProperties.deviceName.data()); + + Features enabledDeviceFeatures = {.m_Vulkan13Features = {.dynamicRendering = vk::True}}; + QueueAllocation queueAllocation = FindAppropriateQueueAllocation(&deviceToUse); + Device device = {&context, &deviceToUse, &enabledDeviceFeatures, {queueAllocation}, "Primary Device"}; + + vk::Queue commandQueue = device.GetQueue(queueAllocation.m_Family, 1); + + Swapchain swapchain = {&window, &device, "Primary Chain"}; + + Pipeline pipeline = CreatePipeline(&device, &swapchain); + + Camera camera = { + {0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f}, + 70.0_deg, + Cast(swapchain.m_Extent.width / swapchain.m_Extent.height), + }; + + // Persistent variables + vk::Viewport viewport = { + .x = 0, + .y = Cast(swapchain.m_Extent.height), + .width = Cast(swapchain.m_Extent.width), + .height = -Cast(swapchain.m_Extent.height), + .minDepth = 0.0, + .maxDepth = 1.0, + }; + + vk::Rect2D scissor = { + .offset = {0, 0}, + .extent = swapchain.m_Extent, + }; + + vk::ImageMemoryBarrier topOfThePipeBarrier = { + .oldLayout = vk::ImageLayout::eUndefined, + .newLayout = vk::ImageLayout::eColorAttachmentOptimal, + .srcQueueFamilyIndex = queueAllocation.m_Family, + .dstQueueFamilyIndex = queueAllocation.m_Family, + .subresourceRange = + { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + vk::ImageMemoryBarrier renderToPresentBarrier = { + .oldLayout = vk::ImageLayout::eColorAttachmentOptimal, + .newLayout = vk::ImageLayout::ePresentSrcKHR, + .srcQueueFamilyIndex = queueAllocation.m_Family, + .dstQueueFamilyIndex = queueAllocation.m_Family, + .subresourceRange = + { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + // Per-frame data + eastl::fixed_vector buffers; + + // Frames + eastl::fixed_vector frames; + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) + { + // TODO FIX: This section can cause dangling pointers due to copy/bad moves. + buffers.emplace_back(&device, sizeof camera, vk::BufferUsageFlagBits::eUniformBuffer, "Camera Uniform"); + frames.emplace_back(&device, queueAllocation.m_Family, i); + } + + u32 frameIndex = 0; + while (window.Poll()) + { + Frame *currentFrame = &frames[frameIndex]; + + auto result = device.m_Device.waitForFences(1, ¤tFrame->m_FrameAvailableFence, vk::True, MaxValue); + ERROR_IF(Failed(result), "Waiting for fence {} failed. Cause: {}", frameIndex, result) + THEN_ABORT(result); + + u32 imageIndex; + result = device.m_Device.acquireNextImageKHR(swapchain.m_Swapchain, MaxValue, + currentFrame->m_ImageAcquireSem, nullptr, &imageIndex); + if (Failed(result)) + { + switch (result) + { + case vk::Result::eErrorOutOfDateKHR: + case vk::Result::eSuboptimalKHR: + INFO("Recreating Swapchain. Cause: {}", result); + swapchain.Create(&window); + viewport.y = Cast(swapchain.m_Extent.height); + viewport.width = Cast(swapchain.m_Extent.width); + viewport.height = -Cast(swapchain.m_Extent.height); + scissor.extent = swapchain.m_Extent; + break; + default: + ERROR("Waiting for swapchain image {} failed. Cause: {}", frameIndex, result) + THEN_ABORT(result); + } + } + + result = device.m_Device.resetFences(1, ¤tFrame->m_FrameAvailableFence); + ERROR_IF(Failed(result), "Fence {} reset failed. Cause: {}", frameIndex, result) + THEN_ABORT(result); + + result = device.m_Device.resetCommandPool(currentFrame->m_Pool, {}); + ERROR_IF(Failed(result), "Command pool {} reset failed. Cause: {}", frameIndex, result) + THEN_ABORT(result); + + vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex]; + vk::Image currentImage = swapchain.m_Images[imageIndex]; + vk::CommandBuffer cmd = currentFrame->AllocateCommandBuffer(); + + topOfThePipeBarrier.image = currentImage; + renderToPresentBarrier.image = currentImage; + + vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit}; + result = cmd.begin(&beginInfo); + ERROR_IF(Failed(result), "Command buffer begin failed. Cause: {}", result) + THEN_ABORT(result); + + cmd.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eColorAttachmentOutput, + {}, 0, nullptr, 0, nullptr, 1, &topOfThePipeBarrier); + + // Render + vk::RenderingAttachmentInfo attachmentInfo = { + .imageView = currentImageView, + .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, 1.0f}, + }; + + vk::RenderingInfo renderingInfo = { + .renderArea = {.extent = swapchain.m_Extent}, + .layerCount = 1, + .colorAttachmentCount = 1, + .pColorAttachments = &attachmentInfo, + }; + + cmd.beginRendering(&renderingInfo); + + cmd.setViewport(0, 1, &viewport); + cmd.setScissor(0, 1, &scissor); + cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.m_Pipeline); + cmd.draw(3, 1, 0, 0); + + cmd.endRendering(); + + cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe, + {}, 0, nullptr, 0, nullptr, 1, &renderToPresentBarrier); + + result = cmd.end(); + ERROR_IF(Failed(result), "Command buffer end failed. Cause: {}", result) + THEN_ABORT(result); + + vk::PipelineStageFlags waitDstStage = vk::PipelineStageFlagBits::eColorAttachmentOutput; + vk::SubmitInfo submitInfo = { + .waitSemaphoreCount = 1, + .pWaitSemaphores = ¤tFrame->m_ImageAcquireSem, + .pWaitDstStageMask = &waitDstStage, + .commandBufferCount = 1, + .pCommandBuffers = &cmd, + .signalSemaphoreCount = 1, + .pSignalSemaphores = ¤tFrame->m_RenderFinishSem, + }; + result = commandQueue.submit(1, &submitInfo, currentFrame->m_FrameAvailableFence); + ERROR_IF(Failed(result), "Command queue submit failed. Cause: {}", result) + THEN_ABORT(result); + + vk::PresentInfoKHR presentInfo = { + .waitSemaphoreCount = 1, + .pWaitSemaphores = ¤tFrame->m_RenderFinishSem, + .swapchainCount = 1, + .pSwapchains = &swapchain.m_Swapchain, + .pImageIndices = &imageIndex, + .pResults = nullptr, + }; + result = commandQueue.presentKHR(&presentInfo); + if (Failed(result)) + { + switch (result) + { + case vk::Result::eErrorOutOfDateKHR: + case vk::Result::eSuboptimalKHR: + INFO("Recreating Swapchain. Cause: {}", result); + swapchain.Create(&window); + viewport.y = Cast(swapchain.m_Extent.height); + viewport.width = Cast(swapchain.m_Extent.width); + viewport.height = -Cast(swapchain.m_Extent.height); + scissor.extent = swapchain.m_Extent; + break; + default: + ERROR("Command queue present failed. Cause: {}", result) + THEN_ABORT(result); + } + } + frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; + } + + auto result = device.m_Device.waitIdle(); + ERROR_IF(Failed(result), "Wait idle failed. Cause: {}", result); + + return 0; +} + +Frame::Frame(const Device *device, const u32 queueFamilyIndex, const u32 frameCount) +{ + m_Device = device; + + const vk::CommandPoolCreateInfo commandPoolCreateInfo = { + .flags = vk::CommandPoolCreateFlagBits::eTransient, + .queueFamilyIndex = queueFamilyIndex, + }; + vk::Result result = device->m_Device.createCommandPool(&commandPoolCreateInfo, nullptr, &m_Pool); + ERROR_IF(Failed(result), "Could not command pool for frame {}. Cause: {}", frameCount, result) + THEN_ABORT(result); + + constexpr vk::FenceCreateInfo fenceCreateInfo = {.flags = vk::FenceCreateFlagBits::eSignaled}; + result = device->m_Device.createFence(&fenceCreateInfo, nullptr, &m_FrameAvailableFence); + ERROR_IF(Failed(result), "Could not create a fence for frame {}. Cause: {}", frameCount, result) + THEN_ABORT(result); + + constexpr vk::SemaphoreCreateInfo semaphoreCreateInfo = {}; + result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_ImageAcquireSem); + ERROR_IF(Failed(result), "Could not create IA semaphore for frame {}. Cause: {}", frameCount, result) + THEN_ABORT(result); + result = device->m_Device.createSemaphore(&semaphoreCreateInfo, nullptr, &m_RenderFinishSem); + ERROR_IF(Failed(result), "Could not create RF semaphore for frame {}. Cause: {}", frameCount, result) + THEN_ABORT(result); + + DEBUG("Frame {} created successfully.", frameCount); +} + +vk::CommandBuffer +Frame::AllocateCommandBuffer() const +{ + const vk::CommandBufferAllocateInfo allocateInfo = { + .commandPool = m_Pool, .level = vk::CommandBufferLevel::ePrimary, .commandBufferCount = 1}; + + vk::CommandBuffer commandBuffer; + vk::Result result = m_Device->m_Device.allocateCommandBuffers(&allocateInfo, &commandBuffer); + ERROR_IF(Failed(result), "Command buffer allocation failed. Cause: {}", result) + THEN_ABORT(result); + + return commandBuffer; +} +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::PipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = { + .vertexBindingDescriptionCount = 0, + .pVertexBindingDescriptions = nullptr, + .vertexAttributeDescriptionCount = 0, + .pVertexAttributeDescriptions = nullptr, + }; + vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = { + .topology = vk::PrimitiveTopology::eTriangleList, + .primitiveRestartEnable = vk::False, + }; + + vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { + .viewportCount = 1, + .scissorCount = 1, + }; + + vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = { + .depthClampEnable = vk::False, + .rasterizerDiscardEnable = vk::False, + .polygonMode = vk::PolygonMode::eFill, + .cullMode = vk::CullModeFlagBits::eNone, + .frontFace = vk::FrontFace::eCounterClockwise, + .depthBiasEnable = vk::False, + .lineWidth = 1.0, + }; + vk::PipelineMultisampleStateCreateInfo multisampleStateCreateInfo = { + .rasterizationSamples = vk::SampleCountFlagBits::e1, + .sampleShadingEnable = vk::False, + }; + vk::PipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = { + .depthTestEnable = vk::False, + .depthWriteEnable = vk::False, + }; + vk::PipelineColorBlendAttachmentState colorBlendAttachmentState = { + .blendEnable = vk::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 = vk::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; +} + +Frame::~Frame() +{ + m_Device->m_Device.destroy(m_RenderFinishSem, nullptr); + m_Device->m_Device.destroy(m_ImageAcquireSem, nullptr); + m_Device->m_Device.destroy(m_FrameAvailableFence, nullptr); + m_Device->m_Device.destroy(m_Pool, nullptr); + + DEBUG("Destoryed Frame"); +} \ No newline at end of file diff --git a/samples/02_box/camera.cpp b/samples/02_box/camera.cpp new file mode 100644 index 0000000..ce66129 --- /dev/null +++ b/samples/02_box/camera.cpp @@ -0,0 +1,16 @@ +// ============================================= +// Aster: camera.cpp +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#include "camera.h" + +#include +#include +#include + +Camera::Camera(const vec3 position, const vec3 direction, const f32 verticalFov, const f32 aspectRatio) + : m_Projection{glm::perspective(verticalFov, aspectRatio, 1.0f, 100.0f)} + , m_View{lookAt(position, direction + position, vec3(0, 1, 0))} +{ +} \ No newline at end of file diff --git a/samples/02_box/camera.h b/samples/02_box/camera.h new file mode 100644 index 0000000..6a0365b --- /dev/null +++ b/samples/02_box/camera.h @@ -0,0 +1,14 @@ +// ============================================= +// Aster: camera.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +struct Camera +{ + mat4 m_Projection; + mat4 m_View; + + Camera(vec3 position, vec3 direction, f32 verticalFov, f32 aspectRatio); +}; diff --git a/samples/02_box/shader/box.ps.hlsl b/samples/02_box/shader/box.ps.hlsl new file mode 100644 index 0000000..f85d053 --- /dev/null +++ b/samples/02_box/shader/box.ps.hlsl @@ -0,0 +1,9 @@ +#version 450 +#pragma shader_stage(fragment) + +layout (location = 0) in vec3 inColor; +layout (location = 0) out vec4 outColor; + +void main() { + outColor = vec4(inColor, 1.0); +} \ No newline at end of file diff --git a/samples/02_box/shader/box.vs.hlsl b/samples/02_box/shader/box.vs.hlsl new file mode 100644 index 0000000..a2c7905 --- /dev/null +++ b/samples/02_box/shader/box.vs.hlsl @@ -0,0 +1,28 @@ +struct VSIn { + int idx : SV_VERTEXID; +}; + +struct VSOut +{ + float4 Pos : SV_POSITION; + [[vk::location(0)]] float3 Color : COLOR0; +}; + +VSOut main(VSIn input) { + float3 points[] = { + float3(-0.5f, -0.5f, 0.0f), + float3(0.5f, -0.5f, 0.0f), + float3(0.0f, 0.5f, 0.0f) + }; + float3 colors[] = { + float3( 1.0f, 0.0f, 0.0f ), + float3( 0.0f, 1.0f, 0.0f ), + float3( 0.0f, 0.0f, 1.0f ), + }; + + VSOut output; + output.Pos = float4(points[input.idx], 1.0f); + output.Color = colors[input.idx]; + + return output; +} \ No newline at end of file diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index a3e353a..e4023c3 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.13) -add_subdirectory("01_triangle") add_subdirectory("00_util") +add_subdirectory("01_triangle") +add_subdirectory("02_box")