Commit 44638d6c authored by Simeon Hermann's avatar Simeon Hermann
Browse files

[#10] created ShaderProgram class, basic shaders and glslc-compile.bat

parent 6fed231d
......@@ -6,4 +6,6 @@ set(vkcv_sources
${vkcv_source}/vkcv/Window.cpp
${vkcv_source}/vkcv/CoreManager.hpp
${vkcv_source}/vkcv/CoreManager.cpp
${vkcv_source}/vkcv/ShaderProgram.hpp
${vkcv_source}/vkcv/ShaderProgram.cpp
)
......@@ -32,6 +32,10 @@ int main(int argc, const char** argv) {
default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl;
}
vkcv::ShaderProgram shaderProgram = vkcv::ShaderProgram::create(context);
shaderProgram.addShader(VK_SHADER_STAGE_VERTEX_BIT, "../../../../../shaders/vert.spv");
shaderProgram.addShader(VK_SHADER_STAGE_FRAGMENT_BIT, "../../../../../shaders/frag.spv");
while (window.isWindowOpen()) {
window.pollEvents();
}
......
C:\VulkanSDK\1.2.170.0\Bin32\glslc.exe shader.vert -o vert.spv
C:\VulkanSDK\1.2.170.0\Bin32\glslc.exe shader.frag -o frag.spv
pause
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor;
void main() {
gl_Position = vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
}
\ No newline at end of file
/**
* @authors Simeon Hermann
* @file src/vkcv/ShaderProgram.cpp
* @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
*/
#include "ShaderProgram.hpp"
#include <fstream>
#include <iostream>
std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
namespace vkcv {
ShaderProgram::ShaderProgram(vkcv::Context& context)
: m_context(context)
{}
std::vector<char> ShaderProgram::readFile(const std::string& filepath) {
std::ifstream file(filepath, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("The file could not be opened.");
}
size_t fileSize = (size_t)file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
return buffer;
}
VkShaderModule ShaderProgram::createShaderModule(const std::vector<char>& shaderCode) {
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = shaderCode.size();
createInfo.pCode = reinterpret_cast<const uint32_t*>(shaderCode.data());
VkShaderModule shaderModule;
if (vkCreateShaderModule(m_context.getDevice(), &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw std::runtime_error("Failed to create shader module!");
}
return shaderModule;
}
VkPipelineShaderStageCreateInfo ShaderProgram::createShaderStage(VkShaderModule& shaderModule, VkShaderStageFlagBits shaderStage) {
VkPipelineShaderStageCreateInfo shaderStageInfo{};
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStageInfo.stage = shaderStage;
shaderStageInfo.module = shaderModule;
shaderStageInfo.pName = "main";
return shaderStageInfo;
}
ShaderProgram::~ShaderProgram() {
}
ShaderProgram ShaderProgram::create(vkcv::Context& context) {
return ShaderProgram(context);
}
void ShaderProgram::addShader(VkShaderStageFlagBits shaderStage, const std::string& filepath) {
if (containsShaderStage(shaderStage)) {
throw std::runtime_error("Shader program already contains this particular shader stage.");
}
else {
auto shaderCode = readFile(filepath);
VkShaderModule shaderModule = createShaderModule(shaderCode);
VkPipelineShaderStageCreateInfo shaderInfo = createShaderStage(shaderModule, shaderStage);
m_shaderStagesList.push_back(shaderInfo);
vkDestroyShaderModule(m_context.getDevice(), shaderModule, nullptr);
}
}
bool ShaderProgram::containsShaderStage(VkShaderStageFlagBits shaderStage) {
for (int i = 0; i < m_shaderStagesList.size(); i++) {
if (m_shaderStagesList[i].stage == shaderStage) {
return true;
}
}
return false;
}
bool ShaderProgram::deleteShaderStage(VkShaderStageFlagBits shaderStage) {
for (int i = 0; i < m_shaderStagesList.size() - 1; i++) {
if (m_shaderStagesList[i].stage == shaderStage) {
m_shaderStagesList.erase(m_shaderStagesList.begin() + i);
return true;
}
}
return false;
}
std::vector<VkPipelineShaderStageCreateInfo> ShaderProgram::getShaderStages() {
return m_shaderStagesList;
}
int ShaderProgram::getShaderStagesCount() {
return m_shaderStagesList.size();
}
}
#pragma once
/**
* @authors Simeon Hermann
* @file src/vkcv/ShaderProgram.hpp
* @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
*/
#define GLFW_INCLUDE_VULKAN
#include <vector>
#include <map>
#include <vulkan/vulkan.hpp>
#include "Context.hpp"
namespace vkcv {
class ShaderProgram final {
private:
vkcv::Context& m_context;
std::vector<VkPipelineShaderStageCreateInfo> m_shaderStagesList;
/**
* Constructor of ShaderProgram requires a context for the logical device.
* @param context of the app
*/
ShaderProgram(vkcv::Context& context);
/**
* Reads the file of a given shader code.
* Only used within the class.
* @param[in] relative path to the shader code
* @return vector of chars as a buffer for the code
*/
std::vector<char> readFile(const std::string& filepath);
/**
* Creates a shader module that encapsulates the read shader code.
* Only used within the class.
* Shader modules are destroyed after respective shader stages are created.
* @param[in] a vector of chars as a buffer for the code
* @return shader module
*/
VkShaderModule createShaderModule(const std::vector<char>& shaderCode);
/**
* Creates a shader stage (info struct) for the to be added shader.
* Only used within the class.
* @param[in] Shader module that encapsulates the shader code
* @param[in] flag that signals the respective shaderStage
* @return pipeline shader stage info struct
*/
VkPipelineShaderStageCreateInfo createShaderStage(VkShaderModule& shaderModule, VkShaderStageFlagBits shaderStage);
public:
/**
* destructor of ShaderProgram, does nothing so far
*/
~ShaderProgram();
/**
* Creates a shader program.
* So far it only calls the constructor.
* @param[in] context of the app
*/
static ShaderProgram create(vkcv::Context& context);
/**
* Adds a shader into the shader program.
* The shader is only added if the shader program does not contain the particular shader stage already.
* Contains: (1) reading of the code, (2) creation of a shader module, (3) creation of a shader stage, (4) adding to the shader stage list, (5) destroying of the shader module
* @param[in] flag that signals the respective shaderStage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
* @param[in] relative path to the shader code (e.g. "../../../../../shaders/vert.spv")
*/
void addShader(VkShaderStageFlagBits shaderStage, const std::string& filepath);
/**
* Tests if the shader program contains a certain shader stage.
* @param[in] flag that signals the respective shader stage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
* @return boolean that is true if the shader program contains the shader stage
*/
bool containsShaderStage(VkShaderStageFlagBits shaderStage);
/**
* Deletes the given shader stage in the shader program.
* @param[in] flag that signals the respective shader stage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
* @return boolean that is false if the shader stage was not found in the shader program
*/
bool deleteShaderStage(VkShaderStageFlagBits shaderStage);
/**
* Returns a list with all the shader stages in the shader program.
* Needed for the transfer to the pipeline.
* @return vector list with all shader stage info structs
*/
std::vector<VkPipelineShaderStageCreateInfo> getShaderStages();
/**
* Returns the number of shader stages in the shader program.
* Needed for the transfer to the pipeline.
* @return integer with the number of stages
*/
int getShaderStagesCount();
};
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment