Engine²
Open-source game engine written in C++.
Loading...
Searching...
No Matches
ShaderDescriptor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "utils/webgpu.hpp"
4
5#include "Logger.hpp"
8#include "spdlog/fmt/fmt.h"
14
15#include <filesystem>
16#include <fstream>
17#include <list>
18#include <optional>
19
20namespace Graphic::Resource {
22 public:
23 ShaderDescriptor() = default;
24 ~ShaderDescriptor() override = default;
25
26 ShaderDescriptor &setShader(std::string_view source)
27 {
28 this->_shaderSource = source;
29 return *this;
30 }
31 ShaderDescriptor &setShaderFromFile(const std::filesystem::path &path)
32 {
33 if (!std::filesystem::exists(path))
34 {
35 Log::Error("Shader file does not exist");
36 return *this;
37 }
38 std::ifstream file(path);
39 if (!file.is_open())
40 {
41 Log::Error("Failed to open shader file");
42 return *this;
43 }
44 std::stringstream buffer;
45 buffer << file.rdbuf();
46 file.close();
47 return setShader(buffer.str());
48 }
49
50 ShaderDescriptor &setVertexEntryPoint(std::string_view entryPoint)
51 {
52 this->_vertexEntryPoint = entryPoint;
53 return *this;
54 }
55
56 ShaderDescriptor &setFragmentEntryPoint(std::string_view entryPoint)
57 {
58 this->_fragmentEntryPoint = entryPoint;
59 return *this;
60 }
61
63 {
64 this->_vertexBufferLayouts.push_back(layout);
65 return *this;
66 }
67
69 {
70 return *std::next(this->_vertexBufferLayouts.begin(), index);
71 }
72
74 {
75 this->_bindGroupLayouts.push_back(layout);
76 return *this;
77 }
78
80 {
81 return *std::next(this->_bindGroupLayouts.begin(), index);
82 }
83
85 {
86 this->_outputColorFormats.push_back(state);
87 return *this;
88 }
89
91 {
92 this->_outputDepthFormat = state;
93 return *this;
94 }
95
96 ShaderDescriptor &setCullMode(wgpu::CullMode mode)
97 {
98 this->_cullMode = mode;
99 return *this;
100 }
101
102 ShaderDescriptor &setPrimitiveTopology(wgpu::PrimitiveTopology topology)
103 {
104 this->_primitiveTopology = topology;
105 return *this;
106 }
107
108 ShaderDescriptor &setName(std::string_view name)
109 {
110 this->_name = name;
111 return *this;
112 }
113
127 std::vector<Utils::ValidationError> validate(void) const override
128 {
129 std::vector<Utils::ValidationError> errors;
130 if (!this->_shaderSource.has_value())
131 {
132 errors.emplace_back("Shader source is not set", "ShaderDescriptor",
134 }
135 if (!this->_name.has_value())
136 {
137 errors.emplace_back("Shader name is not set ('Unnamed' will be used)", "ShaderDescriptor",
139 }
140 if (this->_vertexBufferLayouts.empty())
141 {
142 errors.emplace_back("No vertex buffer layouts added", "ShaderDescriptor",
144 }
145 if (!this->_vertexEntryPoint.has_value())
146 {
147 errors.emplace_back("Vertex entry point is not set ('vs_main' will be used)", "ShaderDescriptor",
149 }
150 if (!this->_fragmentEntryPoint.has_value())
151 {
152 errors.emplace_back("Fragment entry point is not set ('fs_main' will be used)", "ShaderDescriptor",
154 }
155 for (size_t i = 0; i < this->_vertexBufferLayouts.size(); i++)
156 {
157 auto layoutErrors = std::next(this->_vertexBufferLayouts.begin(), i)->validate();
158 for (const auto &error : layoutErrors)
159 {
160 errors.emplace_back(error.message, fmt::format("ShaderDescriptor::({}){}", i, error.location),
161 error.severity);
162 }
163 }
164 for (size_t i = 0; i < this->_bindGroupLayouts.size(); i++)
165 {
166 auto layoutErrors = std::next(this->_bindGroupLayouts.begin(), i)->validate();
167 for (const auto &error : layoutErrors)
168 {
169 errors.emplace_back(error.message, fmt::format("ShaderDescriptor::({}){}", i, error.location),
170 error.severity);
171 }
172 }
173 for (size_t i = 0; i < this->_outputColorFormats.size(); i++)
174 {
175 auto stateErrors = std::next(this->_outputColorFormats.begin(), i)->validate();
176 for (const auto &error : stateErrors)
177 {
178 errors.emplace_back(error.message, fmt::format("ShaderDescriptor::({}){}", i, error.location),
179 error.severity);
180 }
181 }
182 if (this->_outputDepthFormat.has_value())
183 {
184 auto stateErrors = this->_outputDepthFormat->validate();
185 for (const auto &error : stateErrors)
186 {
187 errors.emplace_back(error.message, fmt::format("ShaderDescriptor::DepthStencil{}", error.location),
188 error.severity);
189 }
190 }
191
192 return errors;
193 }
194
195 const std::string &getName() const { return this->_name.has_value() ? this->_name.value() : _DEFAULT_NAME; }
196 const std::list<Utils::BindGroupLayout> &getBindGroupLayouts() const { return this->_bindGroupLayouts; }
197 const std::list<Utils::VertexBufferLayout> &getVertexBufferLayouts() const { return this->_vertexBufferLayouts; }
198 const std::list<Utils::ColorTargetState> &getOutputColorFormats() const { return this->_outputColorFormats; }
199 const std::optional<Utils::DepthStencilState> &getOutputDepthFormat() const { return this->_outputDepthFormat; }
200 const std::optional<std::string> &getShaderSource() const { return this->_shaderSource; }
201 const std::string &getFragmentEntryPoint() const
202 {
203 return this->_fragmentEntryPoint.has_value() ? this->_fragmentEntryPoint.value() :
205 }
206 const std::string &getVertexEntryPoint() const
207 {
208 return this->_vertexEntryPoint.has_value() ? this->_vertexEntryPoint.value() : _DEFAULT_VERTEX_ENTRY_POINT;
209 }
210 wgpu::PrimitiveTopology getPrimitiveTopology() const { return this->_primitiveTopology; }
211 wgpu::CullMode getCullMode() const { return this->_cullMode; }
212
213 private:
214 inline const static std::string _DEFAULT_FRAGMENT_ENTRY_POINT = "fs_main";
215 inline const static std::string _DEFAULT_VERTEX_ENTRY_POINT = "vs_main";
216 inline const static std::string _DEFAULT_NAME = "Unnamed";
217
218 std::optional<std::string> _name;
219 std::list<Utils::BindGroupLayout> _bindGroupLayouts;
220 std::list<Utils::VertexBufferLayout> _vertexBufferLayouts;
221 std::list<Utils::ColorTargetState> _outputColorFormats;
222 std::optional<std::string> _shaderSource;
223 std::optional<std::string> _fragmentEntryPoint;
224 std::optional<std::string> _vertexEntryPoint;
225 std::optional<Utils::DepthStencilState> _outputDepthFormat;
226 wgpu::PrimitiveTopology _primitiveTopology = wgpu::PrimitiveTopology::TriangleList;
227 wgpu::CullMode _cullMode = wgpu::CullMode::Back;
228};
229} // namespace Graphic::Resource
const std::optional< std::string > & getShaderSource() const
Definition ShaderDescriptor.hpp:200
const std::string & getVertexEntryPoint() const
Definition ShaderDescriptor.hpp:206
const std::list< Utils::ColorTargetState > & getOutputColorFormats() const
Definition ShaderDescriptor.hpp:198
std::optional< std::string > _vertexEntryPoint
Definition ShaderDescriptor.hpp:224
const std::string & getName() const
Definition ShaderDescriptor.hpp:195
std::optional< std::string > _fragmentEntryPoint
Definition ShaderDescriptor.hpp:223
const std::list< Utils::BindGroupLayout > & getBindGroupLayouts() const
Definition ShaderDescriptor.hpp:196
ShaderDescriptor & setPrimitiveTopology(wgpu::PrimitiveTopology topology)
Definition ShaderDescriptor.hpp:102
wgpu::CullMode _cullMode
Definition ShaderDescriptor.hpp:227
ShaderDescriptor & setVertexEntryPoint(std::string_view entryPoint)
Definition ShaderDescriptor.hpp:50
ShaderDescriptor & setShaderFromFile(const std::filesystem::path &path)
Definition ShaderDescriptor.hpp:31
ShaderDescriptor & setName(std::string_view name)
Definition ShaderDescriptor.hpp:108
ShaderDescriptor & setCullMode(wgpu::CullMode mode)
Definition ShaderDescriptor.hpp:96
std::optional< Utils::DepthStencilState > _outputDepthFormat
Definition ShaderDescriptor.hpp:225
ShaderDescriptor & setFragmentEntryPoint(std::string_view entryPoint)
Definition ShaderDescriptor.hpp:56
Utils::VertexBufferLayout & getVertexBufferLayout(size_t index)
Definition ShaderDescriptor.hpp:68
static const std::string _DEFAULT_NAME
Definition ShaderDescriptor.hpp:216
static const std::string _DEFAULT_VERTEX_ENTRY_POINT
Definition ShaderDescriptor.hpp:215
static const std::string _DEFAULT_FRAGMENT_ENTRY_POINT
Definition ShaderDescriptor.hpp:214
ShaderDescriptor & addBindGroupLayout(const Utils::BindGroupLayout &layout)
Definition ShaderDescriptor.hpp:73
std::list< Utils::ColorTargetState > _outputColorFormats
Definition ShaderDescriptor.hpp:221
~ShaderDescriptor() override=default
ShaderDescriptor & addOutputColorFormat(const Utils::ColorTargetState &state)
Definition ShaderDescriptor.hpp:84
wgpu::PrimitiveTopology _primitiveTopology
Definition ShaderDescriptor.hpp:226
std::optional< std::string > _shaderSource
Definition ShaderDescriptor.hpp:222
std::list< Utils::VertexBufferLayout > _vertexBufferLayouts
Definition ShaderDescriptor.hpp:220
Utils::BindGroupLayout & getBindGroupLayout(size_t index)
Definition ShaderDescriptor.hpp:79
wgpu::CullMode getCullMode() const
Definition ShaderDescriptor.hpp:211
wgpu::PrimitiveTopology getPrimitiveTopology() const
Definition ShaderDescriptor.hpp:210
std::vector< Utils::ValidationError > validate(void) const override
Validate the ShaderDescriptor and all contained layouts/states.
Definition ShaderDescriptor.hpp:127
const std::string & getFragmentEntryPoint() const
Definition ShaderDescriptor.hpp:201
const std::list< Utils::VertexBufferLayout > & getVertexBufferLayouts() const
Definition ShaderDescriptor.hpp:197
std::optional< std::string > _name
Definition ShaderDescriptor.hpp:218
ShaderDescriptor & addVertexBufferLayout(const Utils::VertexBufferLayout &layout)
Definition ShaderDescriptor.hpp:62
std::list< Utils::BindGroupLayout > _bindGroupLayouts
Definition ShaderDescriptor.hpp:219
ShaderDescriptor & setShader(std::string_view source)
Definition ShaderDescriptor.hpp:26
ShaderDescriptor & setOutputDepthFormat(const Utils::DepthStencilState &state)
Definition ShaderDescriptor.hpp:90
const std::optional< Utils::DepthStencilState > & getOutputDepthFormat() const
Definition ShaderDescriptor.hpp:199
Definition BindGroupLayout.hpp:13
Definition ColorTargetState.hpp:8
Definition DepthStencilState.hpp:8
Definition IValidable.hpp:26
Definition VertexBufferLayout.hpp:11
Definition AGPUBuffer.hpp:6
void Error(const T &msg) noexcept
Definition Logger.hpp:51
@ Warning
Definition IValidable.hpp:13
@ Error
Definition IValidable.hpp:14