Starting to unhardcode, pipelines are now created from outside

This commit is contained in:
Blue 2023-10-16 15:47:47 -03:00
parent 2b33897b4a
commit dc3ac2fdf5
Signed by: blue
GPG Key ID: 9B203B252A63EE38
16 changed files with 386 additions and 159 deletions

View File

@ -22,4 +22,6 @@ set(HEADERS
add_library(engine STATIC ${SOURCES}) add_library(engine STATIC ${SOURCES})
add_subdirectory(program)
target_include_directories(engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -8,7 +8,8 @@ Engine::Engine::Engine() :
physicalDevice(nullptr), physicalDevice(nullptr),
logicalDevice(nullptr), logicalDevice(nullptr),
deviceExtensionNames(), deviceExtensionNames(),
deviceExtensions() deviceExtensions(),
programs()
{ {
addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
} }
@ -31,6 +32,13 @@ void Engine::Engine::enableDebug() {
instance->enableDebug(); instance->enableDebug();
} }
void Engine::Engine::addProgram(const Program& program) {
programs.emplace_back(program);
if (logicalDevice != nullptr)
logicalDevice->addProgram(program);
}
void Engine::Engine::initVulkan() { void Engine::Engine::initVulkan() {
instance->initialize(window->getRequiredVulkanExtensions()); instance->initialize(window->getRequiredVulkanExtensions());
surface = new Surface(instance, window); surface = new Surface(instance, window);
@ -38,7 +46,10 @@ void Engine::Engine::initVulkan() {
pickPhysicalDevice(); pickPhysicalDevice();
logicalDevice = new LogicalDevice(physicalDevice, surface, deviceExtensions, instance->getLayers()); logicalDevice = new LogicalDevice(physicalDevice, surface, deviceExtensions, instance->getLayers());
logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv"); //logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv");
for (const Program& program : programs)
logicalDevice->addProgram(program);
logicalDevice->createSwapChain(); logicalDevice->createSwapChain();
} }
@ -53,6 +64,7 @@ void Engine::Engine::cleanup() {
surface = nullptr; surface = nullptr;
instance->deinitialize(); instance->deinitialize();
programs.clear();
} }
void Engine::Engine::pickPhysicalDevice() { void Engine::Engine::pickPhysicalDevice() {

View File

@ -26,6 +26,7 @@
#include "instance.h" #include "instance.h"
#include "physicaldevice.h" #include "physicaldevice.h"
#include "logicaldevice.h" #include "logicaldevice.h"
#include "program/program.h"
namespace Engine { namespace Engine {
@ -39,6 +40,7 @@ public:
void run(); void run();
void addDeviceExtension(const std::string& extensionName); void addDeviceExtension(const std::string& extensionName);
void enableDebug(); void enableDebug();
void addProgram(const Program& program);
private: private:
void initVulkan(); void initVulkan();
@ -56,6 +58,7 @@ private:
LogicalDevice* logicalDevice; LogicalDevice* logicalDevice;
std::set<std::string> deviceExtensionNames; std::set<std::string> deviceExtensionNames;
std::vector<const char*> deviceExtensions; std::vector<const char*> deviceExtensions;
std::vector<Program> programs;
}; };

View File

@ -17,8 +17,6 @@ Engine::LogicalDevice::LogicalDevice(
graphicsQueue(), graphicsQueue(),
presentQueue(), presentQueue(),
renderPass(), renderPass(),
pipelineLayout(),
graphicsPipeline(),
commandPool(), commandPool(),
commandBuffers(), commandBuffers(),
imageAvailableSemaphores(), imageAvailableSemaphores(),
@ -26,7 +24,6 @@ Engine::LogicalDevice::LogicalDevice(
inFlightFences(), inFlightFences(),
currentFrame(0), currentFrame(0),
framebufferResized(false), framebufferResized(false),
hasPipeline(false),
surface(surface), surface(surface),
surfaceFormat(surface->chooseSwapSurfaceFormat(phys->swapChainSupport)), surfaceFormat(surface->chooseSwapSurfaceFormat(phys->swapChainSupport)),
swapChain(nullptr) swapChain(nullptr)
@ -45,10 +42,7 @@ Engine::LogicalDevice::LogicalDevice(
Engine::LogicalDevice::~LogicalDevice() { Engine::LogicalDevice::~LogicalDevice() {
clearSwapChain(); clearSwapChain();
if (hasPipeline) { pipelines.clear();
vkDestroyPipeline(vk, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(vk, pipelineLayout, nullptr);
}
vkDestroyRenderPass(vk, renderPass, nullptr); vkDestroyRenderPass(vk, renderPass, nullptr);
@ -64,6 +58,10 @@ Engine::LogicalDevice::~LogicalDevice() {
vkDestroyDevice(vk, nullptr); vkDestroyDevice(vk, nullptr);
} }
void Engine::LogicalDevice::addProgram(const Program& program) {
pipelines.emplace_back(program, this);
}
void Engine::LogicalDevice::createSwapChain() { void Engine::LogicalDevice::createSwapChain() {
clearSwapChain(); clearSwapChain();
swapChain = new SwapChain(this); swapChain = new SwapChain(this);
@ -126,25 +124,6 @@ VkResult Engine::LogicalDevice::queuePresent(const VkSemaphore& signal, uint32_t
return vkQueuePresentKHR(presentQueue, &presentInfo); return vkQueuePresentKHR(presentQueue, &presentInfo);
} }
VkShaderModule Engine::LogicalDevice::createShaderModule(const std::string& path) {
std::vector<char> code = readFile(path);
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(vk, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
throw std::runtime_error("failed to create shader module!");
return shaderModule;
}
void Engine::LogicalDevice::destroyShaderModule(VkShaderModule shaderModule) {
vkDestroyShaderModule(vk, shaderModule, nullptr);
}
void Engine::LogicalDevice::createDevice( void Engine::LogicalDevice::createDevice(
VkPhysicalDevice physicalDevice, VkPhysicalDevice physicalDevice,
const QueueFamilyIndices& indices, const QueueFamilyIndices& indices,
@ -154,7 +133,6 @@ void Engine::LogicalDevice::createDevice(
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()};
for (uint32_t queueFamily : uniqueQueueFamilies) { for (uint32_t queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo{}; VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@ -248,8 +226,12 @@ void Engine::LogicalDevice::drawFrame() {
resetFence(inFlightFences[currentFrame]); resetFence(inFlightFences[currentFrame]);
if (!pipelines.empty()) {
vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0); vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
recordCommandBuffer(commandBuffers[currentFrame], imageIndex); recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
} else {
std::cout << "no pipelines attached, skipping command buffer record" << std::endl;
}
if (queueSubmitGraphics( if (queueSubmitGraphics(
imageAvailableSemaphores[currentFrame], imageAvailableSemaphores[currentFrame],
@ -413,114 +395,6 @@ void Engine::LogicalDevice::createRenderPass(VkFormat format) {
throw std::runtime_error("failed to create render pass!"); throw std::runtime_error("failed to create render pass!");
} }
void Engine::LogicalDevice::createGraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath) {
if (hasPipeline)
throw std::runtime_error("an attempt to create graphics pipeline for the second time");
VkShaderModule vertShaderModule = createShaderModule(vertexShaderPath);
VkShaderModule fragShaderModule = createShaderModule(fragmentShaderPath);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pushConstantRangeCount = 0;
if (vkCreatePipelineLayout(vk, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
throw std::runtime_error("failed to create pipeline layout!");
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.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if (vkCreateGraphicsPipelines(vk, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS)
throw std::runtime_error("failed to create graphics pipeline!");
destroyShaderModule(fragShaderModule);
destroyShaderModule(vertShaderModule);
hasPipeline = true;
}
void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkExtent2D extent = swapChain->getExtent(); VkExtent2D extent = swapChain->getExtent();
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
@ -542,7 +416,8 @@ void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, u
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); for (const Pipeline& pipeline: pipelines) {
pipeline.bind(commandBuffer);
VkViewport viewport{}; VkViewport viewport{};
viewport.x = 0.0f; viewport.x = 0.0f;
@ -559,6 +434,7 @@ void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, u
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0); vkCmdDraw(commandBuffer, 3, 1, 0, 0);
}
vkCmdEndRenderPass(commandBuffer); vkCmdEndRenderPass(commandBuffer);
@ -572,3 +448,28 @@ void Engine::LogicalDevice::recreateSwapChain() {
phys->recreateSwapChainSupportDetails(surface); phys->recreateSwapChainSupportDetails(surface);
createSwapChain(); createSwapChain();
} }
VkResult Engine::LogicalDevice::createPipelineLayout(const VkPipelineLayoutCreateInfo& info, VkPipelineLayout& out) {
return vkCreatePipelineLayout(vk, &info, nullptr, &out);
}
VkResult Engine::LogicalDevice::createPipeline(VkGraphicsPipelineCreateInfo& info, VkPipeline& out) {
info.renderPass = renderPass;
return vkCreateGraphicsPipelines(vk, VK_NULL_HANDLE, 1, &info, nullptr, &out);
}
VkResult Engine::LogicalDevice::createShaderModule(const VkShaderModuleCreateInfo& info, VkShaderModule& out) {
return vkCreateShaderModule(vk, &info, nullptr, &out);
}
void Engine::LogicalDevice::destroyPipeline(VkPipeline& pipline) {
vkDestroyPipeline(vk, pipline, nullptr);
}
void Engine::LogicalDevice::destroyPipelineLayout(VkPipelineLayout& layout) {
vkDestroyPipelineLayout(vk, layout, nullptr);
}
void Engine::LogicalDevice::destroyShaderModule(VkShaderModule& module) {
vkDestroyShaderModule(vk, module, nullptr);
}

View File

@ -8,6 +8,8 @@
#include "utils.h" #include "utils.h"
#include "physicaldevice.h" #include "physicaldevice.h"
#include "surface.h" #include "surface.h"
#include "program/pipeline.h"
#include "program/program.h"
namespace Engine { namespace Engine {
class SwapChain; class SwapChain;
@ -24,9 +26,9 @@ public:
void createSwapChain(); void createSwapChain();
void clearSwapChain(); void clearSwapChain();
void createGraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath);
void recreateSwapChain(); void recreateSwapChain();
void setResized(); void setResized();
void addProgram(const Program& program);
void drawFrame(); void drawFrame();
@ -42,10 +44,14 @@ public:
void destroyVkImageView(VkImageView& view); void destroyVkImageView(VkImageView& view);
VkResult createVkFrameBuffer(const VkImageView& imageView, const VkExtent2D& extent, VkFramebuffer& out); VkResult createVkFrameBuffer(const VkImageView& imageView, const VkExtent2D& extent, VkFramebuffer& out);
void destroyVkFrameBuffer(VkFramebuffer& buffer); void destroyVkFrameBuffer(VkFramebuffer& buffer);
VkResult createPipeline(VkGraphicsPipelineCreateInfo& info, VkPipeline& out);
VkResult createPipelineLayout(const VkPipelineLayoutCreateInfo& info, VkPipelineLayout& out);
void destroyPipelineLayout(VkPipelineLayout& layout);
void destroyPipeline(VkPipeline& pipline);
VkResult createShaderModule(const VkShaderModuleCreateInfo& info, VkShaderModule& out);
void destroyShaderModule(VkShaderModule& shaderModule);
private: private:
VkShaderModule createShaderModule(const std::string& path);
void destroyShaderModule(VkShaderModule shaderModule);
void createDevice( void createDevice(
VkPhysicalDevice physicalDevice, VkPhysicalDevice physicalDevice,
const QueueFamilyIndices& indices, const QueueFamilyIndices& indices,
@ -73,8 +79,7 @@ private:
VkQueue graphicsQueue; VkQueue graphicsQueue;
VkQueue presentQueue; VkQueue presentQueue;
VkRenderPass renderPass; VkRenderPass renderPass;
VkPipelineLayout pipelineLayout; std::vector<Pipeline> pipelines;
VkPipeline graphicsPipeline;
VkCommandPool commandPool; VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers; std::vector<VkCommandBuffer> commandBuffers;
std::vector<VkSemaphore> imageAvailableSemaphores; std::vector<VkSemaphore> imageAvailableSemaphores;
@ -82,7 +87,6 @@ private:
std::vector<VkFence> inFlightFences; std::vector<VkFence> inFlightFences;
uint32_t currentFrame; uint32_t currentFrame;
bool framebufferResized; bool framebufferResized;
bool hasPipeline;
Surface* surface; Surface* surface;
VkSurfaceFormatKHR surfaceFormat; VkSurfaceFormatKHR surfaceFormat;
SwapChain* swapChain; SwapChain* swapChain;

View File

@ -0,0 +1,11 @@
set(SOURCES
pipeline.cpp
program.cpp
)
set(HEADERS
pipeline.h
program.h
)
target_sources(engine PRIVATE ${SOURCES})

149
engine/program/pipeline.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "pipeline.h"
#include "logicaldevice.h"
Engine::Pipeline::Pipeline(const Program& program, LogicalDevice* device):
device(device),
program(program),
vk(),
layout()
{
createLayout();
createPipeline();
}
Engine::Pipeline::Pipeline(const Pipeline& other):
device(other.device),
program(other.program),
vk(),
layout()
{
createLayout();
createPipeline();
}
Engine::Pipeline::~Pipeline() {
device->destroyPipeline(vk);
device->destroyPipelineLayout(layout);
}
void Engine::Pipeline::createLayout() {
VkPipelineLayoutCreateInfo info{};
info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
info.setLayoutCount = 0;
info.pushConstantRangeCount = 0;
if (device->createPipelineLayout(info, layout) != VK_SUCCESS)
throw std::runtime_error("failed to create pipeline layout!");
}
VkShaderModule Engine::Pipeline::createShaderModule(Program::ShaderType type) {
VkShaderModuleCreateInfo info{};
info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
info.codeSize = program.codeSize(type);
info.pCode = program.code(type);
VkShaderModule module;
if (device->createShaderModule(info, module) != VK_SUCCESS)
throw std::runtime_error("failed to create shader module!");
return module;
}
void Engine::Pipeline::createPipeline() {
VkShaderModule vertShaderModule = createShaderModule(Program::vertex);
VkShaderModule fragShaderModule = createShaderModule(Program::fragment);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
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.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = layout;
//pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if (device->createPipeline(pipelineInfo, vk) != VK_SUCCESS)
throw std::runtime_error("failed to create graphics pipeline!");
device->destroyShaderModule(fragShaderModule);
device->destroyShaderModule(vertShaderModule);
}
void Engine::Pipeline::bind(const VkCommandBuffer& buffer) const {
vkCmdBindPipeline(buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk);
}

34
engine/program/pipeline.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <string>
#include <vulkan/vulkan.h>
#include "program.h"
namespace Engine {
class LogicalDevice;
class Pipeline {
public:
Pipeline(const Program& program, LogicalDevice* device);
Pipeline(const Pipeline& other);
~Pipeline();
void bind(const VkCommandBuffer& buffer) const;
private:
void createLayout();
void createPipeline();
VkShaderModule createShaderModule(Program::ShaderType type);
private:
LogicalDevice* device;
const Program& program;
VkPipeline vk;
VkPipelineLayout layout;
};
}

View File

@ -0,0 +1,38 @@
#include "program.h"
Engine::Program::Program():
vertexShader(),
fragmentShader()
{}
std::size_t Engine::Program::codeSize(ShaderType type) const {
switch (type) {
case vertex:
return vertexShader.size();
case fragment:
return fragmentShader.size();
}
return 0;
}
const uint32_t* Engine::Program::code(ShaderType type) const {
switch (type) {
case vertex:
return reinterpret_cast<const uint32_t*>(vertexShader.data());
case fragment:
return reinterpret_cast<const uint32_t*>(fragmentShader.data());
}
return nullptr;
}
void Engine::Program::loadSPIRV(const std::string& path, ShaderType type) {
switch (type) {
case vertex:
vertexShader = readFile(path);
case fragment:
fragmentShader = readFile(path);
}
}

30
engine/program/program.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <string>
#include <vulkan/vulkan.h>
#include "utils.h"
namespace Engine {
class Program {
public:
enum ShaderType {
vertex,
fragment
};
Program();
void loadSPIRV(const std::string& path, ShaderType type);
std::size_t codeSize(ShaderType type) const;
const uint32_t* code(ShaderType type) const;
private:
std::vector<char> vertexShader;
std::vector<char> fragmentShader;
};
}

View File

@ -13,17 +13,6 @@ Engine::SwapChain::SwapChain(LogicalDevice* logical):
create(); create();
} }
Engine::SwapChain::SwapChain(LogicalDevice* logical, const VkExtent2D& extent):
logical(logical),
vk(),
images(),
extent(extent),
imageViews(),
frameBuffers()
{
create();
}
void Engine::SwapChain::create() { void Engine::SwapChain::create() {
VkResult result = logical->createVkSwapChain(extent, vk); VkResult result = logical->createVkSwapChain(extent, vk);

View File

@ -11,7 +11,6 @@ class SwapChain {
friend class LogicalDevice; friend class LogicalDevice;
public: public:
SwapChain(LogicalDevice* logical); SwapChain(LogicalDevice* logical);
SwapChain(LogicalDevice* logical, const VkExtent2D& extent);
~SwapChain(); ~SwapChain();
VkExtent2D getExtent() const; VkExtent2D getExtent() const;

View File

@ -153,7 +153,7 @@ std::vector<char> Engine::readFile(const std::string& filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary); std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open()) if (!file.is_open())
throw std::runtime_error("failed to open file!"); throw std::runtime_error("failed to open file " + filename);
size_t fileSize = (size_t) file.tellg(); size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize); std::vector<char> buffer(fileSize);

View File

@ -1,9 +1,24 @@
#include "engine/engine.h" #include "engine/engine.h"
#include "engine/program/program.h"
int main() { int main() {
Engine::Engine app; Engine::Engine app;
app.enableDebug(); app.enableDebug();
Engine::Program tl;
Engine::Program br;
//logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv");
tl.loadSPIRV("shaders/tl.vert.spv", Engine::Program::vertex);
tl.loadSPIRV("shaders/shader.frag.spv", Engine::Program::fragment);
br.loadSPIRV("shaders/br.vert.spv", Engine::Program::vertex);
br.loadSPIRV("shaders/shader.frag.spv", Engine::Program::fragment);
app.addProgram(tl);
app.addProgram(br);
try { try {
app.run(); app.run();
} catch (const std::exception& e) { } catch (const std::exception& e) {

20
shaders/br.vert Normal file
View File

@ -0,0 +1,20 @@
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.5, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, -0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}

20
shaders/tl.vert Normal file
View File

@ -0,0 +1,20 @@
#version 450
layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.5, 0.5),
vec2(-0.5, 0.5),
vec2(-0.5, -0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
fragColor = colors[gl_VertexIndex];
}