initial commit

This commit is contained in:
Johanness
2026-05-18 00:03:06 +03:00
commit ea7e73d6a4
183 changed files with 34479 additions and 0 deletions
+424
View File
@@ -0,0 +1,424 @@
#include "RenderPipeline.hpp"
#include "TileLayout.hpp"
#include <array>
#include <cstring>
#include <fstream>
#include <iostream>
#include <stdexcept>
std::vector<char> RenderPipeline::readFile(
const std::string& filename)
{
std::ifstream file(
filename,
std::ios::ate | std::ios::binary
);
if (!file.is_open())
{
throw std::runtime_error(
"Failed to open file: " + filename
);
}
size_t fileSize =
static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
VkShaderModule RenderPipeline::createShaderModule(
const std::vector<char>& code)
{
VkShaderModuleCreateInfo createInfo{};
createInfo.sType =
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size();
createInfo.pCode =
reinterpret_cast<const uint32_t*>(
code.data()
);
VkShaderModule shaderModule;
if (vkCreateShaderModule(
m_device,
&createInfo,
nullptr,
&shaderModule) != VK_SUCCESS)
{
throw std::runtime_error(
"Failed to create shader module"
);
}
return shaderModule;
}
RenderPipeline::RenderPipeline(
VkDevice device,
VkFormat swapchainImageFormat)
: m_device(device)
{
// Render pass
VkAttachmentDescription colorAttachment{};
colorAttachment.format = swapchainImageFormat;
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;
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(
m_device,
&renderPassInfo,
nullptr,
&m_renderPass) != VK_SUCCESS)
{
throw std::runtime_error(
"Failed to create render pass"
);
}
std::cout << "Render pass created" << std::endl;
// Shaders
auto vertShaderCode =
readFile(
"../shaders/bin/textured.vert.spv"
);
auto fragShaderCode =
readFile(
"../shaders/bin/textured.frag.spv"
);
m_vertShaderModule =
createShaderModule(vertShaderCode);
m_fragShaderModule =
createShaderModule(fragShaderCode);
std::cout << "Shaders loaded" << std::endl;
VkPipelineShaderStageCreateInfo vertStageInfo{};
vertStageInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertStageInfo.module = m_vertShaderModule;
vertStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragStageInfo{};
fragStageInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragStageInfo.stage =
VK_SHADER_STAGE_FRAGMENT_BIT;
fragStageInfo.module = m_fragShaderModule;
fragStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] =
{
vertStageInfo,
fragStageInfo
};
// Vertex input
VkVertexInputBindingDescription
bindingDescription{};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate =
VK_VERTEX_INPUT_RATE_VERTEX;
std::array<
VkVertexInputAttributeDescription,
2
> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format =
VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[0].offset =
offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format =
VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[1].offset =
offsetof(Vertex, uv);
VkPipelineVertexInputStateCreateInfo
vertexInputInfo{};
vertexInputInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo
.vertexBindingDescriptionCount = 1;
vertexInputInfo
.pVertexBindingDescriptions =
&bindingDescription;
vertexInputInfo
.vertexAttributeDescriptionCount =
static_cast<uint32_t>(
attributeDescriptions.size()
);
vertexInputInfo
.pVertexAttributeDescriptions =
attributeDescriptions.data();
// Input assembly
VkPipelineInputAssemblyStateCreateInfo
inputAssembly{};
inputAssembly.sType =
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology =
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
// Viewport state (dynamic, values don't matter)
VkViewport dummyViewport{};
dummyViewport.x = 0.0f;
dummyViewport.y = 0.0f;
dummyViewport.width = 1.0f;
dummyViewport.height = 1.0f;
dummyViewport.minDepth = 0.0f;
dummyViewport.maxDepth = 1.0f;
VkRect2D dummyScissor{};
dummyScissor.offset = {0, 0};
dummyScissor.extent = {1, 1};
VkPipelineViewportStateCreateInfo
viewportState{};
viewportState.sType =
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &dummyViewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &dummyScissor;
// Rasterizer
VkPipelineRasterizationStateCreateInfo
rasterizer{};
rasterizer.sType =
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace =
VK_FRONT_FACE_CLOCKWISE;
// Multisampling
VkPipelineMultisampleStateCreateInfo
multisampling{};
multisampling.sType =
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.rasterizationSamples =
VK_SAMPLE_COUNT_1_BIT;
// Dynamic state
VkDynamicState dynamicStates[] =
{
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo
dynamicState{};
dynamicState.sType =
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = 2;
dynamicState.pDynamicStates = dynamicStates;
// Color blend
VkPipelineColorBlendAttachmentState
colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendStateCreateInfo
colorBlending{};
colorBlending.sType =
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments =
&colorBlendAttachment;
// Descriptor set layout
VkDescriptorSetLayoutBinding
samplerLayoutBinding{};
samplerLayoutBinding.binding = 0;
samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType =
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
samplerLayoutBinding.pImmutableSamplers =
nullptr;
samplerLayoutBinding.stageFlags =
VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo
layoutInfo{};
layoutInfo.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
layoutInfo.pBindings = &samplerLayoutBinding;
if (vkCreateDescriptorSetLayout(
m_device,
&layoutInfo,
nullptr,
&m_descriptorSetLayout) != VK_SUCCESS)
{
throw std::runtime_error(
"Failed to create descriptor set layout"
);
}
VkPipelineLayoutCreateInfo
pipelineLayoutInfo{};
pipelineLayoutInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts =
&m_descriptorSetLayout;
if (vkCreatePipelineLayout(
m_device,
&pipelineLayoutInfo,
nullptr,
&m_pipelineLayout) != VK_SUCCESS)
{
throw std::runtime_error(
"Failed to create pipeline layout"
);
}
// Graphics pipeline
VkGraphicsPipelineCreateInfo
pipelineInfo{};
pipelineInfo.sType =
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState =
&vertexInputInfo;
pipelineInfo.pInputAssemblyState =
&inputAssembly;
pipelineInfo.pViewportState =
&viewportState;
pipelineInfo.pRasterizationState =
&rasterizer;
pipelineInfo.pMultisampleState =
&multisampling;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.pColorBlendState =
&colorBlending;
pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.renderPass = m_renderPass;
pipelineInfo.subpass = 0;
if (vkCreateGraphicsPipelines(
m_device,
VK_NULL_HANDLE,
1,
&pipelineInfo,
nullptr,
&m_graphicsPipeline) != VK_SUCCESS)
{
throw std::runtime_error(
"Failed to create graphics pipeline"
);
}
std::cout << "Graphics pipeline created"
<< std::endl;
}
RenderPipeline::~RenderPipeline()
{
release();
}
void RenderPipeline::release()
{
if (m_device == VK_NULL_HANDLE)
{
return;
}
vkDestroyPipeline(
m_device,
m_graphicsPipeline,
nullptr
);
m_graphicsPipeline = VK_NULL_HANDLE;
vkDestroyPipelineLayout(
m_device,
m_pipelineLayout,
nullptr
);
m_pipelineLayout = VK_NULL_HANDLE;
vkDestroyDescriptorSetLayout(
m_device,
m_descriptorSetLayout,
nullptr
);
m_descriptorSetLayout = VK_NULL_HANDLE;
vkDestroyShaderModule(
m_device,
m_vertShaderModule,
nullptr
);
m_vertShaderModule = VK_NULL_HANDLE;
vkDestroyShaderModule(
m_device,
m_fragShaderModule,
nullptr
);
m_fragShaderModule = VK_NULL_HANDLE;
vkDestroyRenderPass(
m_device,
m_renderPass,
nullptr
);
m_renderPass = VK_NULL_HANDLE;
m_device = VK_NULL_HANDLE;
}