neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
shader_program.inl
Go to the documentation of this file.
1// shader_program.inl
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2019, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
25
26namespace neogfx
27{
28 template <typename Base>
30 iType{ aType }
31 {
32 }
33
34 template <typename Base>
36 {
37 return iType;
38 }
39
40 template <typename Base>
42 {
43 return iShaders;
44 }
45
46 template <typename Base>
48 {
49 return iShaders;
50 }
51
52 template <typename Base>
63
64 template <typename Base>
66 {
67 if (iHandle != std::nullopt)
68 service<i_rendering_engine>().destroy_shader_program_object(*iHandle);
69 }
71 template <typename Base>
73 {
74 return iName;
75 }
77 template <typename Base>
79 {
80 for (auto& stage : stages())
81 for (auto& shader : stage->shaders())
82 if (shader->supports(aBufferType))
83 return true;
84 return false;
85 }
87 template <typename Base>
89 {
90 return iHandle != std::nullopt;
91 }
93 template <typename Base>
94 inline void* shader_program<Base>::handle() const
95 {
96 if (!created())
97 {
98 auto newHandle = service<i_rendering_engine>().create_shader_program_object();
99 if (newHandle == nullptr)
100 throw failed_to_create_shader_program("Failed to create shader program object");
101 iHandle = newHandle;
103 return *iHandle;
104 }
105
106 template <typename Base>
108 {
109 return iStages;
110 }
111
112 template <typename Base>
114 {
115 return iStages;
116 }
117
118 template <typename Base>
120 {
121 return stages().at(static_cast<std::size_t>(aStage));
122 }
123
124 template <typename Base>
126 {
127 return stages().at(static_cast<std::size_t>(aStage));
128 }
129
130 template <typename Base>
131 inline const i_shader& shader_program<Base>::shader(const neolib::i_string& aName) const
132 {
133 auto s = iShaderIndex.find(aName);
134 if (s != iShaderIndex.end())
135 return *s->second;
136 throw shader_not_found();
137 }
138
139 template <typename Base>
140 inline i_shader& shader_program<Base>::shader(const neolib::i_string& aName)
141 {
142 return const_cast<i_shader&>(to_const(*this).shader(aName));
143 }
144
145 template <typename Base>
147 {
148 if (have_stage(shader_type::Vertex))
149 return static_cast<const i_vertex_shader&>(*stage(shader_type::Vertex)->shaders()[0]);
150 throw no_vertex_shader();
151 }
152
153 template <typename Base>
155 {
156 return const_cast<i_vertex_shader&>(to_const(*this).vertex_shader());
157 }
158
159 template <typename Base>
161 {
162 if (have_stage(shader_type::Fragment))
163 return static_cast<const i_fragment_shader&>(*stage(shader_type::Fragment)->shaders()[0]);
164 throw no_fragment_shader();
165 }
166
167 template <typename Base>
169 {
170 return const_cast<i_fragment_shader&>(to_const(*this).fragment_shader());
171 }
172
173 template <typename Base>
174 inline bool shader_program<Base>::is_first_in_stage(const i_shader& aShader) const
175 {
176 return &first_in_stage(aShader.type()) == &aShader;
177 }
178
179 template <typename Base>
180 inline bool shader_program<Base>::is_last_in_stage(const i_shader& aShader) const
181 {
182 return &last_in_stage(aShader.type()) == &aShader;
183 }
184
185 template <typename Base>
186 inline const i_shader& shader_program<Base>::first_in_stage(shader_type aStage) const
187 {
188 if (have_stage(aStage))
189 for (auto const& shader : stage(aStage)->shaders())
190 if (shader->enabled())
191 return *shader;
192 throw shader_not_found();
193 }
194
195 template <typename Base>
196 inline const i_shader& shader_program<Base>::last_in_stage(shader_type aStage) const
197 {
198 if (have_stage(aStage))
199 for (auto shader = stage(aStage)->shaders().rbegin(); shader != stage(aStage)->shaders().rend(); ++shader)
200 if ((**shader).enabled())
201 return **shader;
202 throw shader_not_found();
203 }
204
205 template <typename Base>
206 inline const i_shader& shader_program<Base>::next_in_stage(const i_shader& aPreviousShader) const
207 {
208 if (have_stage(aPreviousShader.type()))
209 {
210 auto const& currentStage = stage(aPreviousShader.type());
211 auto shader = std::find_if(currentStage->shaders().begin(), currentStage->shaders().end(), [&aPreviousShader](auto& s) { return &*s == &aPreviousShader; });
212 while(shader != currentStage->shaders().end())
213 {
215 if ((**shader).enabled())
216 return **shader;
217 }
218 }
219 throw shader_not_found();
220 }
221
222 template <typename Base>
224 {
225 if (iShaderIndex.find(aShader->name()) == iShaderIndex.end())
226 {
227 stage(aShader->type())->shaders().push_back(aShader);
228 iShaderIndex.emplace(string{ aShader->name() }, aShader);
229 return *aShader;
230 }
231 throw shader_name_exists();
232 }
233
234 template <typename Base>
235 inline bool shader_program<Base>::dirty() const
236 {
237 for (auto const& stage : stages())
238 for (auto const& shader : stage->shaders())
239 if (shader->dirty())
240 return (iNeedFullUniformUpdate = true);
241 return false;
242 }
243
244 template <typename Base>
246 {
247 for (auto& stage : stages())
248 for (auto& shader : stage->shaders())
249 shader->set_clean();
250 }
251
252 template <typename Base>
254 {
255 for (auto& stage : stages())
256 for (auto& shader : stage->shaders())
257 shader->prepare_uniforms(aContext, *this);
258 }
259
260 template <typename Base>
262 {
263 if (dirty())
264 {
265 compile();
266 link();
267 use();
268 update_uniform_storage();
269 update_uniform_locations();
270 set_clean();
271 }
272 }
273
274 template <typename Base>
276 {
277 for (auto& stage : stages())
278 for (auto& shader : stage->shaders())
280 return true;
281 return false;
282 }
283
284 template <typename Base>
286 {
287 return iActive;
288 }
289
290 template <typename Base>
292 {
293 prepare_uniforms(aContext);
294 make();
295 use();
296 }
297
298 template <typename Base>
300 {
301 activate(aContext);
302 update_uniforms(aContext);
303 }
304
305 template <typename Base>
307 {
308 bool const needIt = iNeedFullUniformUpdate;
309 iNeedFullUniformUpdate = false;
310 return needIt;
311 }
312
313 template <typename Base>
315 {
316 iActive = true;
317 }
318
319 template <typename Base>
321 {
322 iActive = false;
323 }
324}
const i_fragment_shader & fragment_shader() const override
const i_string & name() const override
const stage_t & stage(shader_type aStage) const override
i_shader & add_shader(const neolib::i_ref_ptr< i_shader > &aShader) override
bool need_full_uniform_update() const
void prepare_uniforms(const i_rendering_context &aContext) override
const i_shader & first_in_stage(shader_type aStage) const override
const i_shader & shader(const neolib::i_string &aName) const override
bool is_first_in_stage(const i_shader &aShader) const override
void * handle() const override
bool is_last_in_stage(const i_shader &aShader) const override
const i_vertex_shader & vertex_shader() const override
bool uniforms_changed() const override
bool created() const override
bool supports(vertex_buffer_type aBufferType) const override
void activate(const i_rendering_context &aContext) override
const stages_t & stages() const override
const i_shader & last_in_stage(shader_type aStage) const override
const i_shader & next_in_stage(const i_shader &aPreviousShader) const override
shader_program(const std::string aName)
void instantiate(const i_rendering_context &aContext) override
bool dirty() const override
bool active() const override
shader_stage(shader_type aType)
shader_type type() const override
shaders_t const & shaders() const override
void set_clean() final
Definition shader.hpp:154
void prepare_uniforms(const i_rendering_context &, i_shader_program &) override
Definition shader.hpp:264
bool dirty() const final
Definition shader.hpp:144
bool enabled() const final
Definition shader.hpp:120
bool uniforms_changed() const final
Definition shader.hpp:158
void push_back(abstract_value_type const &aValue) final
Definition vector.hpp:201
ref_ptr< ConcreteType > make_ref(Args &&... args)
void advance(it_type &it, const distance_type distance)
Definition plf_hive.h:81