Starting to unhardcode, pipelines are now created from outside
This commit is contained in:
parent
2b33897b4a
commit
dc3ac2fdf5
@ -22,4 +22,6 @@ set(HEADERS
|
||||
|
||||
add_library(engine STATIC ${SOURCES})
|
||||
|
||||
add_subdirectory(program)
|
||||
|
||||
target_include_directories(engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
@ -8,7 +8,8 @@ Engine::Engine::Engine() :
|
||||
physicalDevice(nullptr),
|
||||
logicalDevice(nullptr),
|
||||
deviceExtensionNames(),
|
||||
deviceExtensions()
|
||||
deviceExtensions(),
|
||||
programs()
|
||||
{
|
||||
addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
}
|
||||
@ -31,6 +32,13 @@ void Engine::Engine::enableDebug() {
|
||||
instance->enableDebug();
|
||||
}
|
||||
|
||||
void Engine::Engine::addProgram(const Program& program) {
|
||||
programs.emplace_back(program);
|
||||
|
||||
if (logicalDevice != nullptr)
|
||||
logicalDevice->addProgram(program);
|
||||
}
|
||||
|
||||
void Engine::Engine::initVulkan() {
|
||||
instance->initialize(window->getRequiredVulkanExtensions());
|
||||
surface = new Surface(instance, window);
|
||||
@ -38,7 +46,10 @@ void Engine::Engine::initVulkan() {
|
||||
pickPhysicalDevice();
|
||||
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();
|
||||
}
|
||||
|
||||
@ -53,6 +64,7 @@ void Engine::Engine::cleanup() {
|
||||
surface = nullptr;
|
||||
|
||||
instance->deinitialize();
|
||||
programs.clear();
|
||||
}
|
||||
|
||||
void Engine::Engine::pickPhysicalDevice() {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "instance.h"
|
||||
#include "physicaldevice.h"
|
||||
#include "logicaldevice.h"
|
||||
#include "program/program.h"
|
||||
|
||||
namespace Engine {
|
||||
|
||||
@ -39,6 +40,7 @@ public:
|
||||
void run();
|
||||
void addDeviceExtension(const std::string& extensionName);
|
||||
void enableDebug();
|
||||
void addProgram(const Program& program);
|
||||
|
||||
private:
|
||||
void initVulkan();
|
||||
@ -56,6 +58,7 @@ private:
|
||||
LogicalDevice* logicalDevice;
|
||||
std::set<std::string> deviceExtensionNames;
|
||||
std::vector<const char*> deviceExtensions;
|
||||
std::vector<Program> programs;
|
||||
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,6 @@ Engine::LogicalDevice::LogicalDevice(
|
||||
graphicsQueue(),
|
||||
presentQueue(),
|
||||
renderPass(),
|
||||
pipelineLayout(),
|
||||
graphicsPipeline(),
|
||||
commandPool(),
|
||||
commandBuffers(),
|
||||
imageAvailableSemaphores(),
|
||||
@ -26,7 +24,6 @@ Engine::LogicalDevice::LogicalDevice(
|
||||
inFlightFences(),
|
||||
currentFrame(0),
|
||||
framebufferResized(false),
|
||||
hasPipeline(false),
|
||||
surface(surface),
|
||||
surfaceFormat(surface->chooseSwapSurfaceFormat(phys->swapChainSupport)),
|
||||
swapChain(nullptr)
|
||||
@ -45,10 +42,7 @@ Engine::LogicalDevice::LogicalDevice(
|
||||
Engine::LogicalDevice::~LogicalDevice() {
|
||||
clearSwapChain();
|
||||
|
||||
if (hasPipeline) {
|
||||
vkDestroyPipeline(vk, graphicsPipeline, nullptr);
|
||||
vkDestroyPipelineLayout(vk, pipelineLayout, nullptr);
|
||||
}
|
||||
pipelines.clear();
|
||||
|
||||
vkDestroyRenderPass(vk, renderPass, nullptr);
|
||||
|
||||
@ -64,6 +58,10 @@ Engine::LogicalDevice::~LogicalDevice() {
|
||||
vkDestroyDevice(vk, nullptr);
|
||||
}
|
||||
|
||||
void Engine::LogicalDevice::addProgram(const Program& program) {
|
||||
pipelines.emplace_back(program, this);
|
||||
}
|
||||
|
||||
void Engine::LogicalDevice::createSwapChain() {
|
||||
clearSwapChain();
|
||||
swapChain = new SwapChain(this);
|
||||
@ -126,25 +124,6 @@ VkResult Engine::LogicalDevice::queuePresent(const VkSemaphore& signal, uint32_t
|
||||
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(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const QueueFamilyIndices& indices,
|
||||
@ -154,7 +133,6 @@ void Engine::LogicalDevice::createDevice(
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()};
|
||||
|
||||
|
||||
for (uint32_t queueFamily : uniqueQueueFamilies) {
|
||||
VkDeviceQueueCreateInfo queueCreateInfo{};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
@ -248,8 +226,12 @@ void Engine::LogicalDevice::drawFrame() {
|
||||
|
||||
resetFence(inFlightFences[currentFrame]);
|
||||
|
||||
vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
|
||||
if (!pipelines.empty()) {
|
||||
vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
|
||||
} else {
|
||||
std::cout << "no pipelines attached, skipping command buffer record" << std::endl;
|
||||
}
|
||||
|
||||
if (queueSubmitGraphics(
|
||||
imageAvailableSemaphores[currentFrame],
|
||||
@ -413,114 +395,6 @@ void Engine::LogicalDevice::createRenderPass(VkFormat format) {
|
||||
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) {
|
||||
VkExtent2D extent = swapChain->getExtent();
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
@ -542,7 +416,8 @@ void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, u
|
||||
|
||||
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{};
|
||||
viewport.x = 0.0f;
|
||||
@ -559,6 +434,7 @@ void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, u
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||
}
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
@ -572,3 +448,28 @@ void Engine::LogicalDevice::recreateSwapChain() {
|
||||
phys->recreateSwapChainSupportDetails(surface);
|
||||
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);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "utils.h"
|
||||
#include "physicaldevice.h"
|
||||
#include "surface.h"
|
||||
#include "program/pipeline.h"
|
||||
#include "program/program.h"
|
||||
|
||||
namespace Engine {
|
||||
class SwapChain;
|
||||
@ -24,9 +26,9 @@ public:
|
||||
|
||||
void createSwapChain();
|
||||
void clearSwapChain();
|
||||
void createGraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath);
|
||||
void recreateSwapChain();
|
||||
void setResized();
|
||||
void addProgram(const Program& program);
|
||||
|
||||
void drawFrame();
|
||||
|
||||
@ -42,10 +44,14 @@ public:
|
||||
void destroyVkImageView(VkImageView& view);
|
||||
VkResult createVkFrameBuffer(const VkImageView& imageView, const VkExtent2D& extent, VkFramebuffer& out);
|
||||
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:
|
||||
VkShaderModule createShaderModule(const std::string& path);
|
||||
void destroyShaderModule(VkShaderModule shaderModule);
|
||||
void createDevice(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
const QueueFamilyIndices& indices,
|
||||
@ -73,8 +79,7 @@ private:
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
VkRenderPass renderPass;
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkPipeline graphicsPipeline;
|
||||
std::vector<Pipeline> pipelines;
|
||||
VkCommandPool commandPool;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
@ -82,7 +87,6 @@ private:
|
||||
std::vector<VkFence> inFlightFences;
|
||||
uint32_t currentFrame;
|
||||
bool framebufferResized;
|
||||
bool hasPipeline;
|
||||
Surface* surface;
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
SwapChain* swapChain;
|
||||
|
11
engine/program/CMakeLists.txt
Normal file
11
engine/program/CMakeLists.txt
Normal 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
149
engine/program/pipeline.cpp
Normal 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
34
engine/program/pipeline.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
38
engine/program/program.cpp
Normal file
38
engine/program/program.cpp
Normal 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
30
engine/program/program.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
@ -13,17 +13,6 @@ Engine::SwapChain::SwapChain(LogicalDevice* logical):
|
||||
create();
|
||||
}
|
||||
|
||||
Engine::SwapChain::SwapChain(LogicalDevice* logical, const VkExtent2D& extent):
|
||||
logical(logical),
|
||||
vk(),
|
||||
images(),
|
||||
extent(extent),
|
||||
imageViews(),
|
||||
frameBuffers()
|
||||
{
|
||||
create();
|
||||
}
|
||||
|
||||
void Engine::SwapChain::create() {
|
||||
VkResult result = logical->createVkSwapChain(extent, vk);
|
||||
|
||||
|
@ -11,7 +11,6 @@ class SwapChain {
|
||||
friend class LogicalDevice;
|
||||
public:
|
||||
SwapChain(LogicalDevice* logical);
|
||||
SwapChain(LogicalDevice* logical, const VkExtent2D& extent);
|
||||
~SwapChain();
|
||||
|
||||
VkExtent2D getExtent() const;
|
||||
|
@ -153,7 +153,7 @@ std::vector<char> Engine::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!");
|
||||
throw std::runtime_error("failed to open file " + filename);
|
||||
|
||||
size_t fileSize = (size_t) file.tellg();
|
||||
std::vector<char> buffer(fileSize);
|
||||
|
15
main.cpp
15
main.cpp
@ -1,9 +1,24 @@
|
||||
#include "engine/engine.h"
|
||||
#include "engine/program/program.h"
|
||||
|
||||
|
||||
int main() {
|
||||
Engine::Engine app;
|
||||
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 {
|
||||
app.run();
|
||||
} catch (const std::exception& e) {
|
||||
|
20
shaders/br.vert
Normal file
20
shaders/br.vert
Normal 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
20
shaders/tl.vert
Normal 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];
|
||||
}
|
Loading…
Reference in New Issue
Block a user