Fixed Function pipeline settings, prepping for Render passes then rendering to the screen
This commit is contained in:
parent
fa14b3fd8f
commit
a8cbb97fd0
12
Makefile
12
Makefile
@ -2,8 +2,10 @@ CPPFLAGS=-g
|
|||||||
LDFLAGS=-lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
|
LDFLAGS=-lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
|
||||||
DEBUGFLAGS=-DDEBUG -fsanitize=address
|
DEBUGFLAGS=-DDEBUG -fsanitize=address
|
||||||
GDBFLAGS=
|
GDBFLAGS=
|
||||||
SRC=$(shell find . -name *.cpp)
|
SRC = $(shell find . -name *.cpp)
|
||||||
OBJ=$(SRC:%.cpp=%.o)
|
OBJ = $(SRC:%.cpp=%.o)
|
||||||
|
VERTEX = $(src/shaders/%.vert=%.spv)
|
||||||
|
FRAGMENT = $(src/shaders/%.frag=%.spv)
|
||||||
|
|
||||||
BIN=build/agnosiaengine
|
BIN=build/agnosiaengine
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ debug: $(BIN)
|
|||||||
|
|
||||||
.PHONY: dep
|
.PHONY: dep
|
||||||
dep:
|
dep:
|
||||||
sudo pacman -S gcc glfw glm shaderc libxi libxxf86vm gdb
|
sudo pacman -S gcc glfw glm shaderc libxi libxxf86vm gdb glslc
|
||||||
.PHONY: info
|
.PHONY: info
|
||||||
info:
|
info:
|
||||||
@echo "make: Build executable"
|
@echo "make: Build executable"
|
||||||
@ -35,12 +37,14 @@ info:
|
|||||||
@echo "make clean: Clean all files"
|
@echo "make clean: Clean all files"
|
||||||
@echo "make run: Run the executable after building"
|
@echo "make run: Run the executable after building"
|
||||||
|
|
||||||
$(BIN): $(OBJ)
|
$(BIN): $(OBJ) $(VERTEX) $(FRAGMENT)
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
g++ $(CPPFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS)
|
g++ $(CPPFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS)
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
g++ -c -g $< -o $@ $(LDFLAGS)
|
g++ -c -g $< -o $@ $(LDFLAGS)
|
||||||
|
%.spv: %.vert %.frag
|
||||||
|
glslc $< -o $@
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
namespace DeviceControl {
|
namespace DeviceControl {
|
||||||
class devicelibrary {
|
class devicelibrary {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void pickPhysicalDevice(VkInstance& instance);
|
void pickPhysicalDevice(VkInstance& instance);
|
||||||
|
145
src/graphics/graphicspipeline.cpp
Normal file
145
src/graphics/graphicspipeline.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include "graphicspipeline.h"
|
||||||
|
#include <fstream>
|
||||||
|
namespace Graphics {
|
||||||
|
std::vector<VkDynamicState> dynamicStates = {
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR
|
||||||
|
};
|
||||||
|
VkPipelineLayout pipelineLayout;
|
||||||
|
|
||||||
|
static std::vector<char> 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!");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fileSize = (size_t) file.tellg();
|
||||||
|
std::vector<char> buffer(fileSize);
|
||||||
|
|
||||||
|
file.seekg(0);
|
||||||
|
file.read(buffer.data(), fileSize);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
VkShaderModule createShaderModule(const std::vector<char>& code, VkDevice& device) {
|
||||||
|
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(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create shader module!");
|
||||||
|
}
|
||||||
|
return shaderModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
void graphicspipeline::destroyGraphicsPipeline(VkDevice& device) {
|
||||||
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
|
if(Global::enableValidationLayers) std::cout << "Destroyed Layout Pipeline safely\n" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void graphicspipeline::createGraphicsPipeline(VkDevice& device) {
|
||||||
|
// Note to self, for some reason the working directory is not where a read file is called from, but the project folder!
|
||||||
|
auto vertShaderCode = readFile("src/shaders/vert.spv");
|
||||||
|
auto fragShaderCode = readFile("src/shaders/frag.spv");
|
||||||
|
VkShaderModule vertShaderModule = createShaderModule(vertShaderCode, device);
|
||||||
|
VkShaderModule fragShaderModule = createShaderModule(fragShaderCode, device);
|
||||||
|
|
||||||
|
// ------------------ STAGE 1 - INPUT ASSEMBLER ---------------- //
|
||||||
|
// This can get a little complicated, normally, vertices are loaded in sequential order, with an element buffer however, you can specify the indices yourself!
|
||||||
|
// Using an element buffer means you can reuse vertices, which can lead to optimizations. If you set PrimRestart to TRUE, you can utilize the _STRIP modes with special indices
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
|
||||||
|
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
inputAssembly.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
// ------------------ STAGE 2 - VERTEX SHADER ------------------ //
|
||||||
|
// this will be revisited, right now we are hardcoding shader data, so we tell it to not load anything, but that will change.
|
||||||
|
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";
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
|
||||||
|
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
vertexInputInfo.vertexBindingDescriptionCount = 0;
|
||||||
|
vertexInputInfo.pVertexBindingDescriptions = nullptr;
|
||||||
|
vertexInputInfo.vertexAttributeDescriptionCount = 0;
|
||||||
|
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
|
||||||
|
|
||||||
|
// ------------------- STAGE 5 - RASTERIZATION ----------------- //
|
||||||
|
// Take Vertex shader vertices and fragmentize them for the frament shader. The rasterizer also can perform depth testing, face culling, and scissor testing.
|
||||||
|
// In addition, it can also be configured for wireframe rendering.
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizer{};
|
||||||
|
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
// Render regardless of the near and far planes, useful for shadow maps, requires GPU feature *depthClamp*
|
||||||
|
rasterizer.depthClampEnable = VK_FALSE;
|
||||||
|
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||||
|
// MODE_FILL, fill polygons, MODE_LINE, draw wireframe, MODE_POINT, draw vertices. Anything other than fill requires GPU feature *fillModeNonSolid*
|
||||||
|
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
|
rasterizer.lineWidth = 1.0f;
|
||||||
|
// How to cull the faces, right here we cull the back faces and tell the rasterizer front facing vertices are ordered clockwise.
|
||||||
|
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
|
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
|
// Whether or not to add depth values. e.x. for shadow maps.
|
||||||
|
rasterizer.depthBiasEnable = VK_FALSE;
|
||||||
|
|
||||||
|
// ------------------ STAGE 6 - FRAGMENT SHADER ---------------- //
|
||||||
|
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};
|
||||||
|
|
||||||
|
// ------------------ STAGE 7 - COLOR BLENDING ----------------- //
|
||||||
|
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;
|
||||||
|
|
||||||
|
// ---------------------- STATE CONTROLS ---------------------- //
|
||||||
|
VkPipelineViewportStateCreateInfo viewportState{};
|
||||||
|
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewportState.viewportCount = 1;
|
||||||
|
viewportState.scissorCount = 1;
|
||||||
|
// Again, this will be revisited, multisampling can be very useful for anti-aliasing, since it is fast, but we won't implement it for now.
|
||||||
|
// Requires GPU feature UNKNOWN eanbled.
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampling{};
|
||||||
|
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
|
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
// Most of the graphics pipeline is set in stone, some of the pipeline state can be modified without recreating it at runtime though!
|
||||||
|
// There are TONS of settings, this would be another TODO to see what else we can mess with dynamically, but right now we just allow dynamic size of the viewport
|
||||||
|
// and dynamic scissor states. Scissors are pretty straightforward, they are basically pixel masks for the rasterizer.
|
||||||
|
// Scissors describe what regions pixels will be stored, it doesnt cut them after being rendered, it stops them from ever being rendered in that area in the first place.
|
||||||
|
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(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create pipeline layout!");
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDestroyShaderModule(device, fragShaderModule, nullptr);
|
||||||
|
vkDestroyShaderModule(device, vertShaderModule, nullptr);
|
||||||
|
|
||||||
|
if(Global::enableValidationLayers) std::cout << "Pipeline Layout created successfully\n" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
10
src/graphics/graphicspipeline.h
Normal file
10
src/graphics/graphicspipeline.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../global.h"
|
||||||
|
|
||||||
|
namespace Graphics {
|
||||||
|
class graphicspipeline {
|
||||||
|
public:
|
||||||
|
void createGraphicsPipeline(VkDevice& device);
|
||||||
|
void destroyGraphicsPipeline(VkDevice& device);
|
||||||
|
};
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "devicelibrary.h" // Device Library includes global, redundant to include with it here
|
#include "devicelibrary.h" // Device Library includes global, redundant to include with it here
|
||||||
#include "debug/vulkandebuglibs.h"
|
#include "debug/vulkandebuglibs.h"
|
||||||
|
#include "graphics/graphicspipeline.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -23,7 +24,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
DeviceControl::devicelibrary deviceLibs;
|
DeviceControl::devicelibrary deviceLibs;
|
||||||
Debug::vulkandebuglibs debugController;
|
Debug::vulkandebuglibs debugController;
|
||||||
|
Graphics::graphicspipeline graphicsPipeline;
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
@ -47,6 +48,7 @@ private:
|
|||||||
deviceLibs.createLogicalDevice(device);
|
deviceLibs.createLogicalDevice(device);
|
||||||
deviceLibs.createSwapChain(window, device);
|
deviceLibs.createSwapChain(window, device);
|
||||||
deviceLibs.createImageViews(device);
|
deviceLibs.createImageViews(device);
|
||||||
|
graphicsPipeline.createGraphicsPipeline(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createInstance() {
|
void createInstance() {
|
||||||
@ -76,6 +78,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
||||||
|
graphicsPipeline.destroyGraphicsPipeline(device);
|
||||||
deviceLibs.destroyImageViews(device);
|
deviceLibs.destroyImageViews(device);
|
||||||
deviceLibs.destroySwapChain(device);
|
deviceLibs.destroySwapChain(device);
|
||||||
vkDestroyDevice(device, nullptr);
|
vkDestroyDevice(device, nullptr);
|
||||||
|
BIN
src/shaders/frag.spv
Normal file
BIN
src/shaders/frag.spv
Normal file
Binary file not shown.
9
src/shaders/shader.frag
Normal file
9
src/shaders/shader.frag
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 fragColor;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
outColor = vec4(fragColor, 1.0);
|
||||||
|
}
|
20
src/shaders/shader.vert
Normal file
20
src/shaders/shader.vert
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
|
vec2 positions[3] = vec2[](
|
||||||
|
vec2(0.0, -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];
|
||||||
|
}
|
BIN
src/shaders/vert.spv
Normal file
BIN
src/shaders/vert.spv
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user