Skip to content

Commit

Permalink
startings of first draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Rinzii committed Aug 21, 2023
1 parent ac05487 commit 01d711f
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 20 deletions.
29 changes: 29 additions & 0 deletions editor/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
project(genesis-editor)

### Currently we require that the editor has all spv binary files in the same directory as the executable
# This may change at a later date. For now, we copy the files to the build directory.

# Set the source and destination directories
set(SOURCE_DIR "${CMAKE_SOURCE_DIR}/editor/bin")

# Get a list of all .spv files in the source directory
file(GLOB SPV_FILES "${SOURCE_DIR}/*.spv")

# This target does the following:
# - Create the destination directory if it does not exist
# - Remove all .spv files from the destination directory if they exist.
# - Copy all .spv files from the source directory to the destination directory

add_custom_target(copy_spv_files ALL
COMMENT "Copying .spv files"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/editor/Debug/bin"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/editor/Release/bin"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/editor/RelWithDebInfo/bin"
COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/editor/Debug/bin/*.spv"
COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/editor/Release/bin/*.spv"
COMMAND ${CMAKE_COMMAND} -E remove "${CMAKE_BINARY_DIR}/editor/RelWithDebInfo/bin/*.spv"
COMMAND ${CMAKE_COMMAND} -E copy ${SPV_FILES} "${CMAKE_BINARY_DIR}/editor/Debug/bin"
COMMAND ${CMAKE_COMMAND} -E copy ${SPV_FILES} "${CMAKE_BINARY_DIR}/editor/Release/bin"
COMMAND ${CMAKE_COMMAND} -E copy ${SPV_FILES} "${CMAKE_BINARY_DIR}/editor/RelWithDebInfo/bin"
DEPENDS ${SPV_FILES}
)

add_executable(genesis-editor)
add_dependencies(genesis-editor copy_spv_files) # The engine requires the .spv files to be copied before it can be built
target_link_libraries(genesis-editor PRIVATE
genesis::lib
genesis::ext
Expand Down
8 changes: 1 addition & 7 deletions engine/include/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ namespace gen
class Application
{
public:
explicit Application(const char * appName, mim::vec2i const & initialSize)
: m_window{initialSize, appName},
m_graphicsDevice{m_window, appName},

{}

explicit Application(const char * appName, mim::vec2i const & initialSize);

void run();

Expand All @@ -33,7 +28,6 @@ namespace gen
GraphicsDevice m_graphicsDevice;
GraphicsPipeline m_graphicsPipeline;


Logger m_logger{"application"};
};

Expand Down
6 changes: 6 additions & 0 deletions engine/include/graphics/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ namespace gen
GEN_NODISCARD vk::SurfaceKHR const & getSurface() const { return m_surface.get(); }
GEN_NODISCARD vk::PhysicalDevice const & getPhysicalDevice() const { return m_gpu.physicalDevice; }
GEN_NODISCARD vk::Device const & getDevice() const { return m_device.get(); }
GEN_NODISCARD vk::UniqueDevice const & getUniqueDevice() const { return m_device; }
GEN_NODISCARD vk::Queue const & getGraphicsQueue() const { return m_graphicsQueue; }
GEN_NODISCARD vk::SwapchainKHR const & getSwapChain() const { return m_swapChain.get(); }
GEN_NODISCARD vk::SwapchainCreateInfoKHR const & getSwapChainInfo() const { return m_swapChainInfo; }
GEN_NODISCARD std::vector<vk::Image> const & getSwapChainImages() const { return m_swapChainImages; }
GEN_NODISCARD std::vector<vk::UniqueImageView> const & getSwapChainImageViews() const { return m_swapChainImageViews; }

/// Setters

Expand Down
24 changes: 21 additions & 3 deletions engine/include/graphics/pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@
#include <vector>

#include "core.hpp"
#include "logger/log.hpp"

#include "device.hpp"

namespace gen
{
struct PipelineConfigInfo
{
vk::Viewport viewport{};
vk::Rect2D scissor{};
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyInfo{};
vk::PipelineTessellationStateCreateInfo tessellationInfo{};
vk::PipelineViewportStateCreateInfo viewportInfo{};
vk::PipelineRasterizationStateCreateInfo rasterizationInfo{};
vk::PipelineMultisampleStateCreateInfo multisampleInfo{};
vk::PipelineDepthStencilStateCreateInfo depthStencilInfo{};
vk::PipelineColorBlendStateCreateInfo colorBlendInfo{};
vk::PipelineColorBlendAttachmentState colorBlendAttachment{};
uint32_t subpass{};
};

class GraphicsPipeline
Expand All @@ -28,23 +40,29 @@ namespace gen
static PipelineConfigInfo defaultPipelineConfigInfo(mim::vec2i extent);

private:
void createRenderPass();

static std::vector<char> readFile(const std::string & filePath);

void createGraphicsPipeline();

void createShaderModule(const std::vector<char> & code, vk::ShaderModule * shaderModule);

void createShaderModule(const std::vector<char> & code);

// NOLINTNEXTLINE The assumption is that the device will outlive the pipeline at all times since a device fundamentally needs a pipeline to exist
GraphicsDevice & m_device;
vk::UniquePipeline m_graphicsPipeline;
vk::UniqueShaderModule m_vertShaderModule;
vk::UniqueShaderModule m_fragShaderModule;

vk::UniqueRenderPass m_renderPass;
vk::UniquePipelineLayout m_pipelineLayout;
vk::UniquePipeline m_graphicsPipeline;

const PipelineConfigInfo m_configInfo;

vk::UniqueInstance m_instance;
vk::DebugUtilsMessengerEXT m_debugMessenger;

Logger m_logger{"graphics"};
};

} // namespace gen
4 changes: 3 additions & 1 deletion engine/include/graphics/vkHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ namespace vk::util

bool checkDeviceExtensionSupport(vk::PhysicalDevice device, const std::vector<const char *> & deviceExtensions);

vk::UniqueShaderModule createShaderModule(vk::Device device, vk::ShaderStageFlagBits shaderStage, std::string const & shaderText);
vk::UniqueShaderModule createShaderModule(vk::Device device, std::vector<char> const & code);

vk::UniqueShaderModule createShaderModuleFromHLSL(vk::Device device, vk::ShaderStageFlagBits shaderStage, std::string const & shaderText);

vk::UniqueSurfaceKHR createWindowSurface(vk::Instance instance, gen::Window const & window);

Expand Down
6 changes: 6 additions & 0 deletions engine/src/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ namespace gen
{
// possibly change this to instead use Update() and Draw() functions

Application::Application(const char * appName, const mim::vec2i & initialSize)
: m_window(initialSize, appName), m_graphicsDevice(m_window, appName),
m_graphicsPipeline(m_graphicsDevice, GraphicsPipeline::defaultPipelineConfigInfo(initialSize))
{
}

void Application::run()
{
gameLoop();
Expand Down
1 change: 1 addition & 0 deletions engine/src/graphics/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace gen
{
static const std::vector<const char *> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
#ifdef GEN_PLATFORM_APPLE
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
#endif
Expand Down
171 changes: 163 additions & 8 deletions engine/src/graphics/pipeline.cpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,121 @@
// Copyright (c) 2023-present Genesis Engine contributors (see LICENSE.txt)

#include "core.hpp"
#include "graphics/pipeline.hpp"
#include "graphics/vkHelpers.hpp"
#include "logger/log.hpp"

#include <array>
#include <filesystem>
#include <fstream>
#include <stdexcept>
#include <vector>
#include <string>
#include <vector>

namespace gen
{
GraphicsPipeline::GraphicsPipeline(GraphicsDevice & device, const PipelineConfigInfo & configInfo)
: m_device{device}, m_configInfo{configInfo}
GraphicsPipeline::GraphicsPipeline(GraphicsDevice & device, const PipelineConfigInfo & configInfo) : m_device{device}, m_configInfo{configInfo}
{
createRenderPass();
createGraphicsPipeline();
m_logger.info("Graphics pipeline constructed");
}

GraphicsPipeline::~GraphicsPipeline()
{
m_logger.info("Graphics pipeline destructed");
}

PipelineConfigInfo GraphicsPipeline::defaultPipelineConfigInfo(const mim::vec2i extent)
{
PipelineConfigInfo configInfo{};

configInfo.viewport.x = 0.0F;
configInfo.viewport.y = 0.0F;
configInfo.viewport.width = static_cast<float>(extent.x);
configInfo.viewport.height = static_cast<float>(extent.y);
configInfo.viewport.minDepth = 0.0F;
configInfo.viewport.maxDepth = 1.0F;
configInfo.scissor.offset = vk::Offset2D{0, 0};
configInfo.scissor.extent = vk::Extent2D{static_cast<u32>(extent.x), static_cast<u32>(extent.y)};

configInfo.inputAssemblyInfo.flags = vk::PipelineInputAssemblyStateCreateFlags{};
configInfo.inputAssemblyInfo.topology = vk::PrimitiveTopology::eTriangleList;
configInfo.inputAssemblyInfo.primitiveRestartEnable = false;

configInfo.viewportInfo.flags = vk::PipelineViewportStateCreateFlags{};
configInfo.viewportInfo.sType = vk::StructureType::ePipelineViewportStateCreateInfo;
configInfo.viewportInfo.viewportCount = 1;
configInfo.viewportInfo.pViewports = &configInfo.viewport;
configInfo.viewportInfo.scissorCount = 1;
configInfo.viewportInfo.pScissors = &configInfo.scissor;

configInfo.rasterizationInfo.flags = vk::PipelineRasterizationStateCreateFlags{};
configInfo.rasterizationInfo.sType = vk::StructureType::ePipelineRasterizationStateCreateInfo;
configInfo.rasterizationInfo.depthClampEnable = false;
configInfo.rasterizationInfo.rasterizerDiscardEnable = false;
configInfo.rasterizationInfo.polygonMode = vk::PolygonMode::eFill;
configInfo.rasterizationInfo.lineWidth = 1.0F;
configInfo.rasterizationInfo.cullMode = vk::CullModeFlagBits::eNone; // TODO: Switch this to eBack once done testing.
configInfo.rasterizationInfo.frontFace = vk::FrontFace::eClockwise;
configInfo.rasterizationInfo.depthBiasEnable = false;
configInfo.rasterizationInfo.depthBiasConstantFactor = 0.0F; // Optional
configInfo.rasterizationInfo.depthBiasClamp = 0.0F; // Optional
configInfo.rasterizationInfo.depthBiasSlopeFactor = 0.0F; // Optional

// Multi-sampling is not currently enabled. This will be enabled later.
configInfo.multisampleInfo.flags = vk::PipelineMultisampleStateCreateFlags{};
configInfo.multisampleInfo.sType = vk::StructureType::ePipelineMultisampleStateCreateInfo;
configInfo.multisampleInfo.rasterizationSamples = vk::SampleCountFlagBits::e1;
configInfo.multisampleInfo.sampleShadingEnable = false;
configInfo.multisampleInfo.minSampleShading = 1.0F; // Optional
configInfo.multisampleInfo.pSampleMask = nullptr; // Optional
configInfo.multisampleInfo.alphaToCoverageEnable = false; // Optional
configInfo.multisampleInfo.alphaToOneEnable = false; // Optional

// implement depth and stencil later

configInfo.colorBlendAttachment.colorWriteMask =
vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
// this implements alpha blending
configInfo.colorBlendAttachment.blendEnable = true;
configInfo.colorBlendAttachment.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha; // Optional
configInfo.colorBlendAttachment.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha; // Optional
configInfo.colorBlendAttachment.colorBlendOp = vk::BlendOp::eAdd; // Optional
configInfo.colorBlendAttachment.srcAlphaBlendFactor = vk::BlendFactor::eOne; // Optional
configInfo.colorBlendAttachment.dstAlphaBlendFactor = vk::BlendFactor::eZero; // Optional
configInfo.colorBlendAttachment.alphaBlendOp = vk::BlendOp::eAdd; // Optional

configInfo.colorBlendInfo.flags = vk::PipelineColorBlendStateCreateFlags{};
configInfo.colorBlendInfo.sType = vk::StructureType::ePipelineColorBlendStateCreateInfo;
configInfo.colorBlendInfo.logicOpEnable = true;
configInfo.colorBlendInfo.logicOp = vk::LogicOp::eCopy; // Optional
configInfo.colorBlendInfo.attachmentCount = 1;
configInfo.colorBlendInfo.pAttachments = &configInfo.colorBlendAttachment;
configInfo.colorBlendInfo.blendConstants[0] = 0.0F; // Optional
configInfo.colorBlendInfo.blendConstants[1] = 0.0F; // Optional
configInfo.colorBlendInfo.blendConstants[2] = 0.0F; // Optional
configInfo.colorBlendInfo.blendConstants[3] = 0.0F; // Optional

configInfo.subpass = 0;

return configInfo;
}

std::vector<char> GraphicsPipeline::readFile(const std::string & filePath)
{
std::ifstream file(filePath, std::ios::ate | std::ios::binary);
// This function is temporary for testing purposes. Will replace later.

const Logger logger{"graphics"};

std::string currentDir = std::filesystem::current_path().string();
std::string path = currentDir + "/" + filePath;

logger.info("Attempting to open file: {}", path);

std::ifstream file(path, std::ios::ate | std::ios::binary);

if (!file.is_open())
{
logger.error("Failed to open file: {}", filePath);
throw std::runtime_error("failed to open file: " + filePath);
}

Expand All @@ -48,13 +131,85 @@ namespace gen
return buffer;
}

void GraphicsPipeline::createGraphicsPipeline()
void GraphicsPipeline::createRenderPass()
{
vk::AttachmentDescription colorAttachment{
{},
m_device.getSwapChainInfo().imageFormat,
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear, // Clear framebuffer to black before drawing a new frame.
vk::AttachmentStoreOp::eStore, // Store the framebuffer to memory after drawing a new frame.
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::ePresentSrcKHR};

vk::AttachmentReference colorAttachmentRef{0, vk::ImageLayout::eColorAttachmentOptimal};

// for the time being we are only doing a single subpass
vk::SubpassDescription subpass{{}, vk::PipelineBindPoint::eGraphics, 0, nullptr, 1, &colorAttachmentRef, nullptr, nullptr, 0, nullptr};

vk::SubpassDependency dependency{
VK_SUBPASS_EXTERNAL,
0,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
{},
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite};

vk::RenderPassCreateInfo renderPassInfo{{}, 1, &colorAttachment, 1, &subpass, 1, &dependency};

m_renderPass = m_device.getUniqueDevice()->createRenderPassUnique(renderPassInfo);
}

void GraphicsPipeline::createShaderModule(const std::vector<char> & code, vk::ShaderModule * shaderModule)
void GraphicsPipeline::createGraphicsPipeline()
{
// This will be removed later.
auto vertShaderCode = readFile("bin/simplePS.spv");
auto fragShaderCode = readFile("bin/simpleVS.spv");

m_vertShaderModule = vk::util::createShaderModule(m_device.getDevice(), vertShaderCode);
m_fragShaderModule = vk::util::createShaderModule(m_device.getDevice(), fragShaderCode);

vk::PipelineShaderStageCreateInfo vertShaderStageInfo{{}, vk::ShaderStageFlagBits::eVertex, m_vertShaderModule.get(), "main"};
vk::PipelineShaderStageCreateInfo fragShaderStageInfo{{}, vk::ShaderStageFlagBits::eFragment, m_fragShaderModule.get(), "main"};

// vk::PipelineVertexInputStateCreateInfo vertexInputInfo{{}, 0, nullptr, 0, nullptr};

std::array<vk::PipelineShaderStageCreateInfo, 2> shaderStages = {vertShaderStageInfo, fragShaderStageInfo};

std::vector<vk::DynamicState> dynamicStates = {vk::DynamicState::eViewport, vk::DynamicState::eScissor};

vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo{{}, static_cast<uint32_t>(dynamicStates.size()), dynamicStates.data()};

vk::PipelineVertexInputStateCreateInfo vertexInputInfo{{}, 0, nullptr, 0, nullptr};

m_pipelineLayout = m_device.getUniqueDevice()->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo{{}, 0, nullptr, 0, nullptr});

vk::GraphicsPipelineCreateInfo pipelineInfo{
{},
2,
shaderStages.data(),
&vertexInputInfo,
&m_configInfo.inputAssemblyInfo,
&m_configInfo.tessellationInfo,
&m_configInfo.viewportInfo,
&m_configInfo.rasterizationInfo,
&m_configInfo.multisampleInfo,
&m_configInfo.depthStencilInfo,
&m_configInfo.colorBlendInfo,
&dynamicStateCreateInfo,
m_pipelineLayout.get(),
m_renderPass.get(),
m_configInfo.subpass,
nullptr, // optional
-1}; // optional

m_graphicsPipeline = m_device.getUniqueDevice()->createGraphicsPipelineUnique(nullptr, pipelineInfo).value;
}

void GraphicsPipeline::createShaderModule(const std::vector<char> & code)
{
}

} // namespace gen
8 changes: 7 additions & 1 deletion engine/src/graphics/vkHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,14 @@ namespace vk::util
return true;
}

vk::UniqueShaderModule createShaderModule(vk::Device device, std::vector<char> const & code)
{
return device.createShaderModuleUnique(
vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), code.size(), reinterpret_cast<const uint32_t *>(code.data())));
}

// Create a Vulkan shader module from HLSL shader code.
vk::UniqueShaderModule createShaderModule(const vk::Device device, vk::ShaderStageFlagBits shaderStage, std::string const & shaderText)
vk::UniqueShaderModule createShaderModuleFromHLSL(const vk::Device device, vk::ShaderStageFlagBits shaderStage, std::string const & shaderText)
{
std::vector<unsigned int> shaderSPV;
if (!HLSLtoSPV(shaderStage, shaderText, shaderSPV))
Expand Down

0 comments on commit 01d711f

Please sign in to comment.