ShaderProgram.cpp 4.39 KB
Newer Older
1
/**
2
 * @authors Simeon Hermann, Leonie Franken
3
4
5
6
 * @file src/vkcv/ShaderProgram.cpp
 * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
 */

7
#include "vkcv/ShaderProgram.hpp"
8
9

namespace vkcv {
Artur Wasmut's avatar
Artur Wasmut committed
10
11
12
13
14
15
16
17
18
    /**
     * 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> readShaderCode(const std::filesystem::path &shaderPath)
	{
		std::ifstream file(shaderPath.string(), std::ios::ate | std::ios::binary);
19
		if (!file.is_open()) {
Artur Wasmut's avatar
Artur Wasmut committed
20
21
		    std::cout << "The file could not be opened." << std::endl;
			return std::vector<char>{};
22
23
24
25
26
		}
		size_t fileSize = (size_t)file.tellg();
		std::vector<char> buffer(fileSize);
		file.seekg(0);
		file.read(buffer.data(), fileSize);
Artur Wasmut's avatar
Artur Wasmut committed
27
28
29
        return buffer;
	}

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	VertexFormat convertFormat(spirv_cross::SPIRType::BaseType basetype, uint32_t vecsize){
        switch (basetype) {
            case spirv_cross::SPIRType::Int:
                switch (vecsize) {
                    case 1:
                        return VertexFormat::INT;
                    case 2:
                        return VertexFormat::INT2;
                    case 3:
                        return VertexFormat::INT3;
                    case 4:
                        return VertexFormat::INT4;
                    default:
                        break;
                }
                break;
            case spirv_cross::SPIRType::Float:
                switch (vecsize) {
                    case 1:
                        return VertexFormat::FLOAT;
                    case 2:
                        return VertexFormat::FLOAT2;
                    case 3:
                        return VertexFormat::FLOAT3;
                    case 4:
                        return VertexFormat::FLOAT4;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        std::cout << "Shader Program Reflection: unknown Vertex Format" << std::endl;
        return VertexFormat::FLOAT;
	}

Artur Wasmut's avatar
Artur Wasmut committed
67
	ShaderProgram::ShaderProgram() noexcept :
68
69
	m_Shaders{},
    m_VertexLayout{}
Artur Wasmut's avatar
Artur Wasmut committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	{}

	bool ShaderProgram::addShader(ShaderStage shaderStage, const std::filesystem::path &shaderPath)
	{
	    if(m_Shaders.find(shaderStage) != m_Shaders.end())
	        std::cout << "Found existing shader stage. Overwriting."  << std::endl;

	    const std::vector<char> shaderCode = readShaderCode(shaderPath);
	    if (shaderCode.empty())
	        return false;
	    else
        {
            Shader shader{shaderCode, shaderStage};
            m_Shaders.insert(std::make_pair(shaderStage, shader));
            return true;
85
        }
86
87
	}

Artur Wasmut's avatar
Artur Wasmut committed
88
89
90
    const Shader &ShaderProgram::getShader(ShaderStage shaderStage) const
    {
	    return m_Shaders.at(shaderStage);
91
92
	}

Artur Wasmut's avatar
Artur Wasmut committed
93
94
95
96
97
98
99
    bool ShaderProgram::existsShader(ShaderStage shaderStage) const
    {
	    if(m_Shaders.find(shaderStage) == m_Shaders.end())
	        return false;
	    else
	        return true;
    }
100

101
    void ShaderProgram::reflectShader(ShaderStage shaderStage)
102
    {
103
        auto shaderCodeChar = m_Shaders.at(shaderStage).shaderCode;
104
        std::vector<uint32_t> shaderCode;
105

106
107
        for (uint32_t i = 0; i < shaderCodeChar.size()/4; i++) {
            shaderCode.push_back(((uint32_t*) shaderCodeChar.data())[i]);
108
109
        }

110
        spirv_cross::Compiler comp(move(shaderCode));
111
112
        spirv_cross::ShaderResources resources = comp.get_shader_resources();

113
114
115
116
117
118
119
120
121
122
123
124
125
        std::vector<VertexInputAttachment> inputVec;
        uint32_t offset = 0;

        for (uint32_t i = 0; i < resources.stage_inputs.size() ; i++){
            auto &u = resources.stage_inputs[i];
            const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);

            VertexInputAttachment input = VertexInputAttachment(comp.get_decoration(u.id,spv::DecorationLocation),
                                                                0,
                                                                convertFormat(base_type.basetype, base_type.vecsize),
                                                                offset);
            inputVec.push_back(input);
            offset += base_type.vecsize * base_type.width/8;
126
        }
127
128

        m_VertexLayout = VertexLayout(inputVec);
129
    }
130
131
132
133

    VertexLayout& ShaderProgram::getVertexLayout(){
        return m_VertexLayout;
	}
134
}