pipelines and renderpasses

This commit is contained in:
Benjamin Kyd
2023-11-20 16:40:52 +00:00
parent 4def2c2ad6
commit 3f44d56597
9 changed files with 401 additions and 185 deletions

View File

@@ -57,7 +57,7 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 0
ColumnLimit: 90
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false

View File

@@ -1,8 +1,13 @@
#include "pipeline.hpp"
#include "device.hpp"
#include "preview_renderer/shader.hpp"
#include "renderpass.hpp"
#include "swapchain.hpp"
#include "yolo/yolo.hpp"
#include <vulkan/vulkan_core.h>
namespace inferno::graphics {
Pipeline* pipeline_create(GraphicsDevice* device)
@@ -12,12 +17,146 @@ Pipeline* pipeline_create(GraphicsDevice* device)
pipeline->Device = device;
pipeline->Swap = swapchain_create(device, device->SurfaceSize);
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};
pipeline->DynamicStateCreateInfo.sType
= VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
pipeline->DynamicStateCreateInfo.dynamicStateCount = dynamicStates.size();
pipeline->DynamicStateCreateInfo.pDynamicStates = dynamicStates.data();
pipeline->VertexInputInfo.sType
= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
pipeline->VertexInputInfo.vertexBindingDescriptionCount = 0;
pipeline->VertexInputInfo.pVertexBindingDescriptions = nullptr; // Optional
pipeline->VertexInputInfo.vertexAttributeDescriptionCount = 0;
pipeline->VertexInputInfo.pVertexAttributeDescriptions
= nullptr; // pipeline->Vptional
pipeline->InputAssembly.sType
= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
pipeline->InputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipeline->InputAssembly.primitiveRestartEnable = VK_FALSE;
// NOTE: This is where the viewport and scissor are set
// In reality, these should be dynamic, so they can be changed
// VkViewport viewport = {};
// viewport.x = 0.f;
// viewport.y = 0.f;
// viewport.width = (float)pipeline->Swap->Extent.width;
// viewport.height = (float)pipeline->Swap->Extent.height;
// viewport.minDepth = 0.f
// viewport.maxDepth = 1.f;
//
// VkRect2D scissor = {};
// scissor.offset = { 0, 0 };
// scissor.extent = pipeline->Swap->Extent;
pipeline->ViewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
pipeline->ViewportState.viewportCount = 1;
pipeline->ViewportState.scissorCount = 1;
pipeline->Rasterizer.sType
= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
pipeline->Rasterizer.depthClampEnable = VK_FALSE; // NOTE: This is for shadow mapping
pipeline->Rasterizer.rasterizerDiscardEnable = VK_FALSE;
pipeline->Rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
pipeline->Rasterizer.lineWidth = 1.f;
pipeline->Rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
pipeline->Rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
pipeline->Rasterizer.depthBiasEnable = VK_FALSE;
pipeline->Rasterizer.depthBiasConstantFactor = 0.f; // Optional
pipeline->Rasterizer.depthBiasClamp = 0.f; // Optional
pipeline->Rasterizer.depthBiasSlopeFactor = 0.f; // Optional
pipeline->Multisampling.sType
= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
pipeline->Multisampling.sampleShadingEnable = VK_FALSE;
pipeline->Multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
pipeline->Multisampling.minSampleShading = 1.0f; // Optional
pipeline->Multisampling.pSampleMask = nullptr; // Optional
pipeline->Multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
pipeline->ColorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT
| VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
// Alpha pipeline->Blending basically
pipeline->ColorBlendAttachment.blendEnable = VK_TRUE;
pipeline->ColorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
pipeline->ColorBlendAttachment.dstColorBlendFactor
= VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
pipeline->ColorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
pipeline->ColorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
pipeline->ColorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
pipeline->ColorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
pipeline->ColorBlending.sType
= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
pipeline->ColorBlending.logicOpEnable = VK_FALSE;
pipeline->ColorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
pipeline->ColorBlending.attachmentCount = 1;
pipeline->ColorBlending.pAttachments = &pipeline->ColorBlendAttachment;
pipeline->ColorBlending.blendConstants[0] = 0.0f; // Optional
pipeline->ColorBlending.blendConstants[1] = 0.0f; // Optional
pipeline->ColorBlending.blendConstants[2] = 0.0f; // Optional
pipeline->ColorBlending.blendConstants[3] = 0.0f; // pipeline->Optional
VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0; // Optional
pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
if (vkCreatePipelineLayout(
device->VulkanDevice, &pipelineLayoutInfo, nullptr, &pipeline->Layout)
!= VK_SUCCESS) {
yolo::error("failed to create pipeline layout!");
return nullptr;
}
return pipeline;
}
void pipeline_cleanup(Pipeline* pipeline)
{
vkDestroyPipeline(
pipeline->Device->VulkanDevice, pipeline->GraphicsPipeline, nullptr);
vkDestroyPipelineLayout(pipeline->Device->VulkanDevice, pipeline->Layout, nullptr);
delete pipeline;
}
void pipeline_configure_to_renderpass(
Pipeline* pipeline, Shader* shader, RenderPass* renderpass)
{
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shader->ShaderStages;
pipelineInfo.pVertexInputState = &pipeline->VertexInputInfo;
pipelineInfo.pInputAssemblyState = &pipeline->InputAssembly;
pipelineInfo.pViewportState = &pipeline->ViewportState;
pipelineInfo.pRasterizationState = &pipeline->Rasterizer;
pipelineInfo.pMultisampleState = &pipeline->Multisampling;
pipelineInfo.pDepthStencilState = nullptr; // Optional
pipelineInfo.pColorBlendState = &pipeline->ColorBlending;
pipelineInfo.pDynamicState = &pipeline->DynamicStateCreateInfo;
pipelineInfo.layout = pipeline->Layout;
pipelineInfo.renderPass = renderpass->RenderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
if (vkCreateGraphicsPipelines(pipeline->Device->VulkanDevice, VK_NULL_HANDLE, 1,
&pipelineInfo, nullptr, &pipeline->GraphicsPipeline)
!= VK_SUCCESS) {
yolo::error("failed to create graphics pipeline!");
}
}
} // namespace inferno::graphics

View File

@@ -1,18 +1,35 @@
#pragma once
#include "graphics.hpp"
#include <vulkan/vulkan_core.h>
namespace inferno::graphics {
struct GraphicsDevice;
struct RenderPass;
struct SwapChain;
struct Shader;
typedef struct Pipeline {
GraphicsDevice* Device;
SwapChain* Swap;
VkPipeline GraphicsPipeline;
VkPipelineLayout Layout;
VkPipelineDynamicStateCreateInfo DynamicStateCreateInfo;
VkPipelineVertexInputStateCreateInfo VertexInputInfo;
VkPipelineInputAssemblyStateCreateInfo InputAssembly;
VkPipelineViewportStateCreateInfo ViewportState;
VkPipelineRasterizationStateCreateInfo Rasterizer;
VkPipelineMultisampleStateCreateInfo Multisampling;
VkPipelineColorBlendAttachmentState ColorBlendAttachment;
VkPipelineColorBlendStateCreateInfo ColorBlending;
} Pipeline;
Pipeline* pipeline_create(GraphicsDevice* device);
void pipeline_cleanup(Pipeline* pipeline);
void pipeline_configure_to_renderpass(Pipeline* pipeline, Shader* shader, RenderPass* renderpass);
}

View File

@@ -0,0 +1,66 @@
#include "renderpass.hpp"
#include "device.hpp"
#include "pipeline.hpp"
#include "swapchain.hpp"
#include "preview_renderer/shader.hpp"
#include "yolo/yolo.hpp"
namespace inferno::graphics {
RenderPass* renderpass_create(GraphicsDevice* device)
{
RenderPass* renderpass = new RenderPass;
renderpass->Device = device;
renderpass->RenderPipeline = pipeline_create(device);
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = renderpass->RenderPipeline->Swap->ImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef; // index = gl_colour in glsl
VkRenderPassCreateInfo renderPassInfo {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
if (vkCreateRenderPass(
device->VulkanDevice, &renderPassInfo, nullptr, &renderpass->RenderPass)
!= VK_SUCCESS) {
yolo::error("failed to create render pass!");
return nullptr;
}
Shader* shader = shader_create(device->VulkanDevice);
shader_load(shader, "res/shaders/vulkan_test");
pipeline_configure_to_renderpass(renderpass->RenderPipeline, shader, renderpass);
return renderpass;
}
void rendepass_cleanup(RenderPass* renderpass)
{
pipeline_cleanup(renderpass->RenderPipeline);
vkDestroyRenderPass(renderpass->Device->VulkanDevice, renderpass->RenderPass, nullptr);
delete renderpass;
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include "graphics.hpp"
namespace inferno::graphics {
struct GraphicsDevice;
struct Pipeline;
typedef struct RenderPass {
GraphicsDevice* Device;
Pipeline* RenderPipeline;
VkRenderPass RenderPass;
VkFramebuffer Framebuffer;
} RenderPass;
RenderPass* renderpass_create(GraphicsDevice* device);
void renderpass_cleanup(RenderPass* renderpass);
}

View File

@@ -12,36 +12,42 @@ struct SwapChainSupportDetails {
std::vector<VkPresentModeKHR> PresentModes;
};
SwapChainSupportDetails device_get_swapchain_support(GraphicsDevice* g, VkPhysicalDevice device)
SwapChainSupportDetails device_get_swapchain_support(
GraphicsDevice* g, VkPhysicalDevice device)
{
SwapChainSupportDetails details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, g->VulkanSurface, &details.Capabilities);
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
device, g->VulkanSurface, &details.Capabilities);
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, g->VulkanSurface, &formatCount, nullptr);
if (formatCount != 0) {
details.Formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, g->VulkanSurface, &formatCount, details.Formats.data());
vkGetPhysicalDeviceSurfaceFormatsKHR(
device, g->VulkanSurface, &formatCount, details.Formats.data());
}
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, g->VulkanSurface, &presentModeCount, nullptr);
vkGetPhysicalDeviceSurfacePresentModesKHR(
device, g->VulkanSurface, &presentModeCount, nullptr);
if (presentModeCount != 0) {
details.PresentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, g->VulkanSurface, &presentModeCount, details.PresentModes.data());
vkGetPhysicalDeviceSurfacePresentModesKHR(
device, g->VulkanSurface, &presentModeCount, details.PresentModes.data());
}
return details;
}
VkSurfaceFormatKHR device_choose_swap_surface_format(const std::vector<VkSurfaceFormatKHR>& availableFormats)
VkSurfaceFormatKHR device_choose_swap_surface_format(
const std::vector<VkSurfaceFormatKHR>& availableFormats)
{
for (const auto& availableFormat : availableFormats) {
if (
availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB
&& availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return availableFormat;
}
}
@@ -49,7 +55,8 @@ VkSurfaceFormatKHR device_choose_swap_surface_format(const std::vector<VkSurface
return availableFormats[0];
}
VkPresentModeKHR device_choose_swap_present_mode(const std::vector<VkPresentModeKHR>& availablePresentModes)
VkPresentModeKHR device_choose_swap_present_mode(
const std::vector<VkPresentModeKHR>& availablePresentModes)
{
for (const auto& availablePresentMode : availablePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
@@ -60,19 +67,18 @@ VkPresentModeKHR device_choose_swap_present_mode(const std::vector<VkPresentMode
return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D device_choose_swap_extent(const VkSurfaceCapabilitiesKHR& capabilities, int width, int height)
VkExtent2D device_choose_swap_extent(
const VkSurfaceCapabilitiesKHR& capabilities, int width, int height)
{
if (capabilities.currentExtent.width != UINT32_MAX) {
return capabilities.currentExtent;
} else {
VkExtent2D actualExtent = { (uint32_t)width, (uint32_t)height };
actualExtent.width = std::max(
capabilities.minImageExtent.width,
actualExtent.width = std::max(capabilities.minImageExtent.width,
std::min(capabilities.maxImageExtent.width, actualExtent.width));
actualExtent.height = std::max(
capabilities.minImageExtent.height,
actualExtent.height = std::max(capabilities.minImageExtent.height,
std::min(capabilities.maxImageExtent.height, actualExtent.height));
return actualExtent;
@@ -83,14 +89,19 @@ SwapChain* swapchain_create(GraphicsDevice* device, glm::ivec2 surface_size)
{
SwapChain* swapchain = new SwapChain();
SwapChainSupportDetails swapChainSupport = device_get_swapchain_support(device, device->VulkanPhysicalDevice);
SwapChainSupportDetails swapChainSupport
= device_get_swapchain_support(device, device->VulkanPhysicalDevice);
VkSurfaceFormatKHR surfaceFormat = device_choose_swap_surface_format(swapChainSupport.Formats);
VkPresentModeKHR presentMode = device_choose_swap_present_mode(swapChainSupport.PresentModes);
VkExtent2D extent = device_choose_swap_extent(swapChainSupport.Capabilities, surface_size.x, surface_size.y);
VkSurfaceFormatKHR surfaceFormat
= device_choose_swap_surface_format(swapChainSupport.Formats);
VkPresentModeKHR presentMode
= device_choose_swap_present_mode(swapChainSupport.PresentModes);
VkExtent2D extent = device_choose_swap_extent(
swapChainSupport.Capabilities, surface_size.x, surface_size.y);
uint32_t imageCount = swapChainSupport.Capabilities.minImageCount + 1;
if (swapChainSupport.Capabilities.maxImageCount > 0 && imageCount > swapChainSupport.Capabilities.maxImageCount) {
if (swapChainSupport.Capabilities.maxImageCount > 0
&& imageCount > swapChainSupport.Capabilities.maxImageCount) {
imageCount = swapChainSupport.Capabilities.maxImageCount;
}
@@ -105,8 +116,10 @@ SwapChain* swapchain_create(GraphicsDevice* device, glm::ivec2 surface_size)
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
QueueFamilyIndices indices = device_get_queue_families(device, device->VulkanPhysicalDevice);
uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
QueueFamilyIndices indices
= device_get_queue_families(device, device->VulkanPhysicalDevice);
uint32_t queueFamilyIndices[]
= { indices.graphicsFamily.value(), indices.presentFamily.value() };
if (indices.graphicsFamily != indices.presentFamily) {
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
@@ -124,15 +137,19 @@ SwapChain* swapchain_create(GraphicsDevice* device, glm::ivec2 surface_size)
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(device->VulkanDevice, &createInfo, nullptr, &swapchain->Handle) != VK_SUCCESS) {
if (vkCreateSwapchainKHR(
device->VulkanDevice, &createInfo, nullptr, &swapchain->Handle)
!= VK_SUCCESS) {
yolo::error("failed to create swap chain!");
exit(1);
}
yolo::info("Swap chain created");
vkGetSwapchainImagesKHR(device->VulkanDevice, swapchain->Handle, &imageCount, nullptr);
vkGetSwapchainImagesKHR(
device->VulkanDevice, swapchain->Handle, &imageCount, nullptr);
swapchain->Images.resize(imageCount);
vkGetSwapchainImagesKHR(device->VulkanDevice, swapchain->Handle, &imageCount, swapchain->Images.data());
vkGetSwapchainImagesKHR(
device->VulkanDevice, swapchain->Handle, &imageCount, swapchain->Images.data());
swapchain->ImageFormat = surfaceFormat.format;
swapchain->Extent = extent;
@@ -174,7 +191,9 @@ void swapchain_image_view_create(SwapChain* swapchain)
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(swapchain->Device->VulkanDevice, &createInfo, nullptr, &swapchain->ImageViews[i]) != VK_SUCCESS) {
if (vkCreateImageView(swapchain->Device->VulkanDevice, &createInfo, nullptr,
&swapchain->ImageViews[i])
!= VK_SUCCESS) {
yolo::error("failed to create image views!");
exit(1);
}

View File

@@ -6,9 +6,10 @@
// #include "gui/layout.hpp"
// #include "renderer/renderer.hpp"
// #include "scene/scene.hpp"
#include "window.hpp"
#include "graphics/pipeline.hpp"
#include "graphics/device.hpp"
#include "graphics/pipeline.hpp"
#include "graphics/renderpass.hpp"
#include "window.hpp"
// #include "preview_renderer/debug.hpp"
// #include "preview_renderer/renderer.hpp"
@@ -37,16 +38,15 @@ InfernoTimer* inferno_timer_create()
return timer;
}
void inferno_timer_cleanup(InfernoTimer* timer)
{
delete timer;
}
void inferno_timer_cleanup(InfernoTimer* timer) { delete timer; }
void inferno_timer_rolling_average(InfernoTimer* timer, int count)
{
if (timer->Times.size() > count)
timer->Times.erase(timer->Times.begin());
timer->RollingAverage = std::accumulate(timer->Times.begin(), timer->Times.end(), std::chrono::duration<double>(0.0)) / count;
timer->RollingAverage = std::accumulate(timer->Times.begin(), timer->Times.end(),
std::chrono::duration<double>(0.0))
/ count;
}
void inferno_timer_start(InfernoTimer* timer)
@@ -94,7 +94,7 @@ InfernoApp* inferno_create()
// Create window
graphics::window_create("Inferno v" INFERNO_VERSION, 1920, 1080);
graphics::GraphicsDevice* device = graphics::device_create();
graphics::Pipeline* p = graphics::pipeline_create(device);
graphics::RenderPass* p = graphics::renderpass_create(device);
// // setup the scene
// scene::Material* basicMaterial = new scene::Material("basic");
@@ -150,12 +150,12 @@ void inferno_preset_gui(InfernoApp* app)
// ImGuiID dockspace_id = ImGui::GetID("main");
//
// ImGui::DockBuilderRemoveNode(dockspace_id); // Clear out existing layout
// ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace); // Add empty node
// ImGui::DockBuilderSetNodeSize(dockspace_id, { 1000, 1000 });
// ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace); // Add empty
// node ImGui::DockBuilderSetNodeSize(dockspace_id, { 1000, 1000 });
//
// ImGuiID dock_main_id = dockspace_id;
// ImGuiID dock_left = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.5f, NULL, &dock_main_id);
// ImGui::DockBuilderDockWindow("Preview", dock_left);
// ImGuiID dock_left = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.5f,
// NULL, &dock_main_id); ImGui::DockBuilderDockWindow("Preview", dock_left);
// ImGui::DockBuilderDockWindow("Render", dock_main_id);
// ImGui::DockBuilderFinish(dockspace_id);
//
@@ -171,13 +171,16 @@ void inferno_move_input(InfernoApp* app, std::chrono::duration<double> deltaTime
// pan only get on hold
static glm::dvec2 lastMousePos;
static int firstClick = 0;
if (glfwGetMouseButton(graphics::window_get_glfw_window(), GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) {
if (glfwGetMouseButton(graphics::window_get_glfw_window(), GLFW_MOUSE_BUTTON_1)
== GLFW_PRESS) {
firstClick++;
if (firstClick == 1) {
glfwGetCursorPos(graphics::window_get_glfw_window(), &lastMousePos.x, &lastMousePos.y);
glfwGetCursorPos(
graphics::window_get_glfw_window(), &lastMousePos.x, &lastMousePos.y);
}
glm::dvec2 tempMousePos = { 0.0f, 0.0f };
glfwGetCursorPos(graphics::window_get_glfw_window(), &tempMousePos.x, &tempMousePos.y);
glfwGetCursorPos(
graphics::window_get_glfw_window(), &tempMousePos.x, &tempMousePos.y);
app->Input->MouseDelta = lastMousePos - tempMousePos;
lastMousePos = tempMousePos;
} else {
@@ -211,7 +214,8 @@ bool inferno_pre(InfernoApp* app)
{
app->FrameCount++;
if (app->FrameCount % 100 == 0) {
yolo::info("Average FPS: {}", 1.0 / inferno_timer_get_time(app->MainTimer).count());
yolo::info(
"Average FPS: {}", 1.0 / inferno_timer_get_time(app->MainTimer).count());
inferno_timer_print(app->MainTimer, false);
}
@@ -229,9 +233,7 @@ bool inferno_pre(InfernoApp* app)
return true;
}
void inferno_end(InfernoApp* app)
{
}
void inferno_end(InfernoApp* app) { }
int inferno_run(InfernoApp* app)
{
@@ -241,7 +243,8 @@ int inferno_run(InfernoApp* app)
// break;
//
// if (glm::length(app->Input->MouseDelta) > 0.0f)
// graphics::camera_mouse_move(app->Scene->Camera, app->Input->MouseDelta);
// graphics::camera_mouse_move(app->Scene->Camera,
// app->Input->MouseDelta);
// if (app->Input->MovementDelta != 0b00000000)
// graphics::camera_move(app->Scene->Camera, app->Input->MovementDelta);
//
@@ -289,7 +292,8 @@ int inferno_run(InfernoApp* app)
// ImGui::End();
// }
//
// if (showPreview && ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar)) {
// if (showPreview && ImGui::Begin("Preview", nullptr,
// ImGuiWindowFlags_NoScrollbar)) {
// if (ImGui::IsWindowHovered()) {
// inferno_move_input(app, inferno_timer_get_time(app->MainTimer));
// } else {
@@ -298,12 +302,14 @@ int inferno_run(InfernoApp* app)
//
// graphics::camera_raster_set_viewport(scene::scene_get_camera(app->Scene),
// { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
// graphics::preview_set_viewport(app->PreviewRenderer, app->Scene->Camera);
// graphics::preview_set_viewport(app->PreviewRenderer,
// app->Scene->Camera);
//
// graphics::preview_draw(app->PreviewRenderer, app->Scene);
// graphics::debug_draw_to_target(app->Scene);
//
// ImTextureID texture = (ImTextureID)graphics::preview_get_rendered_texture(app->PreviewRenderer);
// ImTextureID texture =
// (ImTextureID)graphics::preview_get_rendered_texture(app->PreviewRenderer);
// ImGui::Image(
// texture,
// { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y },
@@ -315,7 +321,8 @@ int inferno_run(InfernoApp* app)
// if (ImGui::Begin("Render")) {
// graphics::rayr_draw(app->RayRenderer);
//
// ImTextureID texture = (ImTextureID)graphics::rayr_get_rendered_texture(app->RayRenderer);
// ImTextureID texture =
// (ImTextureID)graphics::rayr_get_rendered_texture(app->RayRenderer);
// ImGui::Image(
// texture,
// { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y },

View File

@@ -3,13 +3,11 @@
#include <fstream>
#include <iostream>
#include "yolo/yolo.hpp"
namespace inferno::graphics {
static std::unordered_map<GLuint, int> shader2Index = {
{ GL_VERTEX_SHADER, 0 },
{ GL_GEOMETRY_SHADER, 1 },
{ GL_FRAGMENT_SHADER, 2 }
};
static std::unordered_map<GLuint, int> shader2Index = {};
inline std::string trim(std::string& str)
{
@@ -25,164 +23,123 @@ std::string textFromFile(const std::filesystem::path& path)
std::istreambuf_iterator<char>());
}
std::vector<const ShaderPreprocessorDefinition*> getKeys(Shader* shader, std::string key)
{
std::vector<const ShaderPreprocessorDefinition*> ret;
for (const auto& p : shader->PreprocessorDefinitions)
if (p.key == key)
ret.push_back(&p);
return ret;
}
bool checkShader(GLuint uid)
{
GLint isCompiled = 0;
glGetShaderiv(uid, GL_COMPILE_STATUS, &isCompiled);
// glGetShaderiv(uid, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE) {
GLint maxLength = 0;
glGetShaderiv(uid, GL_INFO_LOG_LENGTH, &maxLength);
// glGetShaderiv(uid, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(uid, maxLength, &maxLength, &errorLog[0]);
// glGetShaderInfoLog(uid, maxLength, &maxLength, &errorLog[0]);
for (int i = 0; i < errorLog.size(); i++) {
std::cout << errorLog[i];
}
glDeleteShader(uid);
// glDeleteShader(uid);
return false;
}
return true;
}
Shader* shader_create()
Shader* shader_create(VkDevice device)
{
Shader* shader = new Shader;
shader->Program = 0;
shader->Shaders[0] = GL_NONE;
shader->Shaders[1] = GL_NONE;
shader->Shaders[2] = GL_NONE;
shader->Device = device;
return shader;
}
void shader_cleanup(Shader* shader)
{
for (int i = 0; i < 3; i++) {
if (shader->Shaders[i] == GL_NONE)
continue;
glDeleteShader(shader->Shaders[i]);
}
glDeleteProgram(shader->Program);
vkDestroyShaderModule(shader->Device, shader->VertexShader, nullptr);
vkDestroyShaderModule(shader->Device, shader->FragmentShader, nullptr);
}
void shader_load(Shader* shader, std::filesystem::path path)
{
assert(std::filesystem::exists(path));
std::string loadedShaderSource = textFromFile(path);
// path is the filename, code needs to add .vert.spv or .frag.spv
// std::string shaderPath = "shaders/" + path + ".spv";
for (int i = 0; i < loadedShaderSource.length(); i++) {
const char& c = loadedShaderSource[i];
if (c == '#') {
ShaderPreprocessorDefinition def = { .start = i };
int j;
for (j = ++i; loadedShaderSource[j] != ' '; j++) {
def.key += loadedShaderSource[j];
}
for (j++; loadedShaderSource[j] != '\n'; j++) {
def.def += loadedShaderSource[j];
}
def.end = j;
i = j; // advance i
def.def = trim(def.def);
def.key = trim(def.key);
shader->PreprocessorDefinitions.push_back(def);
}
std::string shaderPath = path.string();
std::string vertexShaderPath = shaderPath + ".vert.spv";
std::string fragmentShaderPath = shaderPath + ".frag.spv";
assert(std::filesystem::exists(vertexShaderPath));
assert(std::filesystem::exists(fragmentShaderPath));
std::string vertexLoadedShaderCode = textFromFile(vertexShaderPath);
VkShaderModuleCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = vertexLoadedShaderCode.size();
createInfo.pCode
= reinterpret_cast<const uint32_t*>(vertexLoadedShaderCode.data());
if (vkCreateShaderModule(
shader->Device, &createInfo, nullptr, &shader->VertexShader)
!= VK_SUCCESS) {
yolo::error("failed to create shader module");
}
// now we have all of the key/value definitions
// we can extract the relavent ones, for example
// "type"
std::vector<const ShaderPreprocessorDefinition*> types = getKeys(shader, "type");
int i = 0;
for (const ShaderPreprocessorDefinition* type : types) {
GLuint glType = GL_NONE;
if (type->def == "vertex")
glType = GL_VERTEX_SHADER;
if (type->def == "geometry")
glType = GL_GEOMETRY_SHADER;
if (type->def == "fragment")
glType = GL_FRAGMENT_SHADER;
shader->ShaderStages[0].sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader->ShaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader->ShaderStages[0].module = shader->VertexShader;
shader->ShaderStages[0].pName = "main";
assert(glType != GL_NONE);
std::string fragmentLoadedShaderCode = textFromFile(fragmentShaderPath);
VkShaderModuleCreateInfo createInfo2 = {};
createInfo2.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo2.codeSize = fragmentLoadedShaderCode.size();
createInfo2.pCode
= reinterpret_cast<const uint32_t*>(fragmentLoadedShaderCode.data());
shader->Shaders[shader2Index[glType]] = glCreateShader(glType);
const char* source = loadedShaderSource.c_str() + type->end;
int end = types.size() - 1 == i ? types.size() : types[i + 1]->start;
int length = end - type->end;
glShaderSource(shader->Shaders[shader2Index[glType]], 1, &source, &length);
i++;
}
}
void shader_link(Shader* shader)
{
shader->Program = glCreateProgram();
for (int i = 0; i < 3; i++) {
if (shader->Shaders[i] == GL_NONE)
continue;
glCompileShader(shader->Shaders[i]);
if (!checkShader(shader->Shaders[i]))
continue;
glAttachShader(shader->Program, shader->Shaders[i]);
if (vkCreateShaderModule(
shader->Device, &createInfo2, nullptr, &shader->FragmentShader)
!= VK_SUCCESS) {
yolo::error("failed to create shader module");
}
glLinkProgram(shader->Program);
shader->ShaderStages[1].sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader->ShaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader->ShaderStages[1].module = shader->FragmentShader;
shader->ShaderStages[1].pName = "main";
}
GLuint shader_get_program(Shader* shader)
{
return shader->Program;
}
void shader_add_attribute(Shader* shader, const std::string& attribute)
{
shader->Attributes[attribute] = glGetAttribLocation(shader->Program, attribute.c_str());
}
void shader_add_uniform(Shader* shader, const std::string& uniform)
{
shader->Uniforms[uniform] = glGetUniformLocation(shader->Program, uniform.c_str());
}
GLuint shader_get_attribute(Shader* shader, const std::string& attribute)
{
return shader->Attributes[attribute];
}
GLuint shader_get_uniform(Shader* shader, const std::string& uniform)
{
return shader->Uniforms[uniform];
}
// void shader_add_attribute(Shader* shader, const std::string& attribute)
// {
// // shader->Attributes[attribute] = glGetAttribLocation(shader->Program,
// attribute.c_str());
// }
//
// void shader_add_uniform(Shader* shader, const std::string& uniform)
// {
// shader->Uniforms[uniform] = glGetUniformLocation(shader->Program,
// uniform.c_str());
// }
//
// GLuint shader_get_attribute(Shader* shader, const std::string& attribute)
// {
// return shader->Attributes[attribute];
// }
//
// GLuint shader_get_uniform(Shader* shader, const std::string& uniform)
// {
// return shader->Uniforms[uniform];
// }
void shader_use(Shader* shader)
{
glUseProgram(shader->Program);
// glUseProgram(shader->Program);
}
void shader_unuse(Shader* shader)
{
glUseProgram(0);
// glUseProgram(0);
}
}

View File

@@ -10,33 +10,23 @@
namespace inferno::graphics {
typedef struct ShaderPreprocessorDefinition {
int start, end;
std::string key;
std::string def;
} shaderpreprocessordefinition;
// TODO: Make general
typedef struct Shader {
GLuint Shaders[3];
GLuint Program;
std::unordered_map<std::string, GLuint> Attributes;
std::unordered_map<std::string, GLuint> Uniforms;
std::vector<ShaderPreprocessorDefinition> PreprocessorDefinitions;
VkDevice Device;
VkShaderModule VertexShader;
VkShaderModule FragmentShader;
VkPipelineShaderStageCreateInfo ShaderStages[2];
VkPipelineVertexInputStateCreateInfo VertexInputInfo;
} Shader;
Shader* shader_create();
Shader* shader_create(VkDevice device);
void shader_cleanup(Shader* shader);
void shader_load(Shader* shader, std::filesystem::path path);
void shader_link(Shader* shader);
GLuint shader_get_program(Shader* shader);
// TODO: Implement shader_reload
void shader_add_attribute(Shader* shader, const std::string& attribute);
void shader_add_uniform(Shader* shader, const std::string& uniform);
GLuint shader_get_attribute(Shader* shader, const std::string& attribute);
GLuint shader_get_uniform(Shader* shader, const std::string& uniform);
// although with vulkan, it's not really necessary
// as the pipeline is created with the shaders
void shader_use(Shader* shader);
void shader_unuse(Shader* shader);