@@ -167,29 +167,27 @@ class SourceShaderCache
167
167
}
168
168
};
169
169
170
+
170
171
/*
171
172
ShaderCallback: Sets constants that can be used in shaders
172
173
*/
173
174
174
- class IShaderConstantSetterRegistry
175
- {
176
- public:
177
- virtual ~IShaderConstantSetterRegistry (){};
178
- virtual void onSetConstants (video::IMaterialRendererServices *services,
179
- bool is_highlevel, const std::string &name) = 0;
180
- };
181
-
182
175
class ShaderCallback : public video ::IShaderConstantSetCallBack
183
176
{
184
- IShaderConstantSetterRegistry *m_scsr;
185
- std::string m_name;
177
+ std::vector<IShaderConstantSetter*> m_setters;
186
178
187
179
public:
188
- ShaderCallback (IShaderConstantSetterRegistry *scsr, const std::string &name):
189
- m_scsr (scsr),
190
- m_name (name)
191
- {}
192
- ~ShaderCallback () {}
180
+ ShaderCallback (const std::vector<IShaderConstantSetterFactory*> &factories)
181
+ {
182
+ for (u32 i = 0 ; i < factories.size (); ++i)
183
+ m_setters.push_back (factories[i]->create ());
184
+ }
185
+
186
+ ~ShaderCallback ()
187
+ {
188
+ for (u32 i = 0 ; i < m_setters.size (); ++i)
189
+ delete m_setters[i];
190
+ }
193
191
194
192
virtual void OnSetConstants (video::IMaterialRendererServices *services, s32 userData)
195
193
{
@@ -198,18 +196,25 @@ class ShaderCallback : public video::IShaderConstantSetCallBack
198
196
199
197
bool is_highlevel = userData;
200
198
201
- m_scsr->onSetConstants (services, is_highlevel, m_name);
199
+ for (u32 i = 0 ; i < m_setters.size (); ++i)
200
+ m_setters[i]->onSetConstants (services, is_highlevel);
202
201
}
203
202
};
204
203
204
+
205
205
/*
206
206
MainShaderConstantSetter: Set basic constants required for almost everything
207
207
*/
208
208
209
209
class MainShaderConstantSetter : public IShaderConstantSetter
210
210
{
211
+ CachedVertexShaderSetting<float , 16 > m_world_view_proj;
212
+ CachedVertexShaderSetting<float , 16 > m_world;
213
+
211
214
public:
212
- MainShaderConstantSetter (IrrlichtDevice *device)
215
+ MainShaderConstantSetter () :
216
+ m_world_view_proj (" mWorldViewProj" ),
217
+ m_world (" mWorld" )
213
218
{}
214
219
~MainShaderConstantSetter () {}
215
220
@@ -219,31 +224,40 @@ class MainShaderConstantSetter : public IShaderConstantSetter
219
224
video::IVideoDriver *driver = services->getVideoDriver ();
220
225
sanity_check (driver);
221
226
222
- // set clip matrix
227
+ // Set clip matrix
223
228
core::matrix4 worldViewProj;
224
229
worldViewProj = driver->getTransform (video::ETS_PROJECTION);
225
230
worldViewProj *= driver->getTransform (video::ETS_VIEW);
226
231
worldViewProj *= driver->getTransform (video::ETS_WORLD);
227
- if (is_highlevel)
228
- services-> setVertexShaderConstant ( " mWorldViewProj " , worldViewProj.pointer (), 16 );
232
+ if (is_highlevel)
233
+ m_world_view_proj. set (* reinterpret_cast < float (*)[ 16 ]>( worldViewProj.pointer ()), services );
229
234
else
230
- services->setVertexShaderConstant (worldViewProj.pointer (), 4 , 4 );
235
+ services->setVertexShaderConstant (worldViewProj.pointer (), 0 , 4 );
231
236
232
- // set world matrix
237
+ // Set world matrix
233
238
core::matrix4 world = driver->getTransform (video::ETS_WORLD);
234
- if (is_highlevel)
235
- services-> setVertexShaderConstant ( " mWorld " , world.pointer (), 16 );
239
+ if (is_highlevel)
240
+ m_world. set (* reinterpret_cast < float (*)[ 16 ]>( world.pointer ()), services );
236
241
else
237
- services->setVertexShaderConstant (world.pointer (), 8 , 4 );
242
+ services->setVertexShaderConstant (world.pointer (), 4 , 4 );
238
243
239
244
}
240
245
};
241
246
247
+
248
+ class MainShaderConstantSetterFactory : public IShaderConstantSetterFactory
249
+ {
250
+ public:
251
+ virtual IShaderConstantSetter* create ()
252
+ { return new MainShaderConstantSetter (); }
253
+ };
254
+
255
+
242
256
/*
243
257
ShaderSource
244
258
*/
245
259
246
- class ShaderSource : public IWritableShaderSource , public IShaderConstantSetterRegistry
260
+ class ShaderSource : public IWritableShaderSource
247
261
{
248
262
public:
249
263
ShaderSource (IrrlichtDevice *device);
@@ -286,22 +300,17 @@ class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterR
286
300
// Shall be called from the main thread.
287
301
void rebuildShaders ();
288
302
289
- void addGlobalConstantSetter (IShaderConstantSetter *setter)
303
+ void addShaderConstantSetterFactory (IShaderConstantSetterFactory *setter)
290
304
{
291
- m_global_setters .push_back (setter);
305
+ m_setter_factories .push_back (setter);
292
306
}
293
307
294
- void onSetConstants (video::IMaterialRendererServices *services,
295
- bool is_highlevel, const std::string &name);
296
-
297
308
private:
298
309
299
310
// The id of the thread that is allowed to use irrlicht directly
300
311
threadid_t m_main_thread;
301
312
// The irrlicht device
302
313
IrrlichtDevice *m_device;
303
- // The set-constants callback
304
- ShaderCallback *m_shader_callback;
305
314
306
315
// Cache of source shaders
307
316
// This should be only accessed from the main thread
@@ -316,9 +325,11 @@ class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterR
316
325
// Queued shader fetches (to be processed by the main thread)
317
326
RequestQueue<std::string, u32, u8, u8> m_get_shader_queue;
318
327
319
- // Global constant setters
320
- // TODO: Delete these in the destructor
321
- std::vector<IShaderConstantSetter*> m_global_setters;
328
+ // Global constant setter factories
329
+ std::vector<IShaderConstantSetterFactory *> m_setter_factories;
330
+
331
+ // Shader callbacks
332
+ std::vector<ShaderCallback *> m_callbacks;
322
333
};
323
334
324
335
IWritableShaderSource* createShaderSource (IrrlichtDevice *device)
@@ -331,8 +342,8 @@ IWritableShaderSource* createShaderSource(IrrlichtDevice *device)
331
342
*/
332
343
ShaderInfo generate_shader (std::string name,
333
344
u8 material_type, u8 drawtype,
334
- IrrlichtDevice *device,
335
- video::IShaderConstantSetCallBack *callback ,
345
+ IrrlichtDevice *device, std::vector<ShaderCallback *> &callbacks,
346
+ const std::vector<IShaderConstantSetterFactory*> &setter_factories ,
336
347
SourceShaderCache *sourcecache);
337
348
338
349
/*
@@ -348,28 +359,24 @@ ShaderSource::ShaderSource(IrrlichtDevice *device):
348
359
{
349
360
assert (m_device); // Pre-condition
350
361
351
- m_shader_callback = new ShaderCallback (this , " default" );
352
-
353
362
m_main_thread = thr_get_current_thread_id ();
354
363
355
364
// Add a dummy ShaderInfo as the first index, named ""
356
365
m_shaderinfo_cache.push_back (ShaderInfo ());
357
366
358
367
// Add main global constant setter
359
- addGlobalConstantSetter (new MainShaderConstantSetter (device ));
368
+ addShaderConstantSetterFactory (new MainShaderConstantSetterFactory ( ));
360
369
}
361
370
362
371
ShaderSource::~ShaderSource ()
363
372
{
364
- for (std::vector<IShaderConstantSetter *>::iterator iter = m_global_setters .begin ();
365
- iter != m_global_setters .end (); ++iter) {
373
+ for (std::vector<ShaderCallback *>::iterator iter = m_callbacks .begin ();
374
+ iter != m_callbacks .end (); ++iter) {
366
375
delete *iter;
367
376
}
368
- m_global_setters.clear ();
369
-
370
- if (m_shader_callback) {
371
- m_shader_callback->drop ();
372
- m_shader_callback = NULL ;
377
+ for (std::vector<IShaderConstantSetterFactory *>::iterator iter = m_setter_factories.begin ();
378
+ iter != m_setter_factories.end (); ++iter) {
379
+ delete *iter;
373
380
}
374
381
}
375
382
@@ -445,8 +452,8 @@ u32 ShaderSource::getShaderIdDirect(const std::string &name,
445
452
return 0 ;
446
453
}
447
454
448
- ShaderInfo info = generate_shader (name, material_type, drawtype, m_device,
449
- m_shader_callback , &m_sourcecache);
455
+ ShaderInfo info = generate_shader (name, material_type, drawtype,
456
+ m_device, m_callbacks, m_setter_factories , &m_sourcecache);
450
457
451
458
/*
452
459
Add shader to caches (add dummy shaders too)
@@ -511,22 +518,16 @@ void ShaderSource::rebuildShaders()
511
518
ShaderInfo *info = &m_shaderinfo_cache[i];
512
519
if (info->name != " " ){
513
520
*info = generate_shader (info->name , info->material_type ,
514
- info->drawtype , m_device, m_shader_callback, &m_sourcecache);
521
+ info->drawtype , m_device, m_callbacks,
522
+ m_setter_factories, &m_sourcecache);
515
523
}
516
524
}
517
525
}
518
526
519
- void ShaderSource::onSetConstants (video::IMaterialRendererServices *services,
520
- bool is_highlevel, const std::string &name)
521
- {
522
- for (u32 i=0 ; i<m_global_setters.size (); i++){
523
- IShaderConstantSetter *setter = m_global_setters[i];
524
- setter->onSetConstants (services, is_highlevel);
525
- }
526
- }
527
527
528
528
ShaderInfo generate_shader (std::string name, u8 material_type, u8 drawtype,
529
- IrrlichtDevice *device, video::IShaderConstantSetCallBack *callback,
529
+ IrrlichtDevice *device, std::vector<ShaderCallback *> &callbacks,
530
+ const std::vector<IShaderConstantSetterFactory*> &setter_factories,
530
531
SourceShaderCache *sourcecache)
531
532
{
532
533
ShaderInfo shaderinfo;
@@ -766,6 +767,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
766
767
geometry_program = shaders_header + geometry_program;
767
768
geometry_program_ptr = geometry_program.c_str ();
768
769
}
770
+ ShaderCallback *cb = new ShaderCallback (setter_factories);
769
771
s32 shadermat = -1 ;
770
772
if (is_highlevel){
771
773
infostream<<" Compiling high level shaders for " <<name<<std::endl;
@@ -782,7 +784,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
782
784
scene::EPT_TRIANGLES, // Geometry shader input
783
785
scene::EPT_TRIANGLE_STRIP, // Geometry shader output
784
786
0 , // Support maximum number of vertices
785
- callback, // Set-constant callback
787
+ cb, // Set-constant callback
786
788
shaderinfo.base_material , // Base material
787
789
1 // Userdata passed to callback
788
790
);
@@ -794,6 +796,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
794
796
dumpShaderProgram (warningstream, " Vertex" , vertex_program);
795
797
dumpShaderProgram (warningstream, " Pixel" , pixel_program);
796
798
dumpShaderProgram (warningstream, " Geometry" , geometry_program);
799
+ delete cb;
797
800
return shaderinfo;
798
801
}
799
802
}
@@ -802,7 +805,7 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
802
805
shadermat = gpu->addShaderMaterial (
803
806
vertex_program_ptr, // Vertex shader program
804
807
pixel_program_ptr, // Pixel shader program
805
- callback, // Set-constant callback
808
+ cb, // Set-constant callback
806
809
shaderinfo.base_material , // Base material
807
810
0 // Userdata passed to callback
808
811
);
@@ -814,9 +817,11 @@ ShaderInfo generate_shader(std::string name, u8 material_type, u8 drawtype,
814
817
<<std::endl;
815
818
dumpShaderProgram (warningstream, " Vertex" , vertex_program);
816
819
dumpShaderProgram (warningstream," Pixel" , pixel_program);
820
+ delete cb;
817
821
return shaderinfo;
818
822
}
819
823
}
824
+ callbacks.push_back (cb);
820
825
821
826
// HACK, TODO: investigate this better
822
827
// Grab the material renderer once more so minetest doesn't crash on exit
0 commit comments