RetroArch
internal_interface.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-2017 ARM Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SPIRV_CROSS_INTERNAL_INTERFACE_HPP
18 #define SPIRV_CROSS_INTERNAL_INTERFACE_HPP
19 
20 // This file must only be included by the shader generated by spirv-cross!
21 
22 #ifndef GLM_FORCE_SWIZZLE
23 #define GLM_FORCE_SWIZZLE
24 #endif
25 
26 #ifndef GLM_FORCE_RADIANS
27 #define GLM_FORCE_RADIANS
28 #endif
29 
30 #include <glm/glm.hpp>
31 
32 #include "barrier.hpp"
33 #include "external_interface.h"
34 #include "image.hpp"
35 #include "sampler.hpp"
36 #include "thread_group.hpp"
37 #include <assert.h>
38 #include <stdint.h>
39 
40 namespace internal
41 {
42 // Adaptor helpers to adapt GLSL access chain syntax to C++.
43 // Don't bother with arrays of arrays on uniforms ...
44 // Would likely need horribly complex variadic template munging.
45 
46 template <typename T>
47 struct Interface
48 {
49  enum
50  {
51  ArraySize = 1,
52  Size = sizeof(T)
53  };
54 
56  : ptr(0)
57  {
58  }
59  T &get()
60  {
61  assert(ptr);
62  return *ptr;
63  }
64 
65  T *ptr;
66 };
67 
68 // For array types, return a pointer instead.
69 template <typename T, unsigned U>
70 struct Interface<T[U]>
71 {
72  enum
73  {
74  ArraySize = U,
75  Size = U * sizeof(T)
76  };
77 
79  : ptr(0)
80  {
81  }
82  T *get()
83  {
84  assert(ptr);
85  return ptr;
86  }
87 
88  T *ptr;
89 };
90 
91 // For case when array size is 1, avoid double dereference.
92 template <typename T>
94 {
95  enum
96  {
97  ArraySize = 1,
98  Size = sizeof(T *)
99  };
100  enum
101  {
103  };
104 
106  : ptr(0)
107  {
108  }
109 
110  T &get()
111  {
112  assert(ptr);
113  return *ptr;
114  }
115 
116  T *ptr;
117 };
118 
119 // Automatically converts a pointer down to reference to match GLSL syntax.
120 template <typename T>
122 {
124  : ptr(ptr)
125  {
126  }
127  T &operator[](unsigned index) const
128  {
129  return *(ptr[index]);
130  }
131  T **ptr;
132 };
133 
134 // We can't have a linear array of T* since T* can be an abstract type in case of samplers.
135 // We also need a list of pointers since we can have run-time length SSBOs.
136 template <typename T, unsigned U>
137 struct PointerInterface<T[U]>
138 {
139  enum
140  {
142  Size = sizeof(T *) * U
143  };
144  enum
145  {
147  };
149  : ptr(0)
150  {
151  }
152 
154  {
155  assert(ptr);
156  return DereferenceAdaptor<T>(ptr);
157  }
158 
159  T **ptr;
160 };
161 
162 // Resources can be more abstract and be unsized,
163 // so we need to have an array of pointers for those cases.
164 template <typename T>
166 {
167 };
168 
169 // POD with no unknown sizes, so we can express these as flat arrays.
170 template <typename T>
172 {
173 };
174 template <typename T>
176 {
177 };
178 template <typename T>
180 {
181 };
182 template <typename T>
184 {
185 };
186 }
187 
189 {
190  struct PPSize
191  {
193  : ptr(0)
194  , size(0)
195  {
196  }
197  void **ptr;
198  size_t size;
199  };
200 
202  {
204  : ptr(0)
205  , size(0)
207  {
208  }
209  void **ptr;
210  size_t size;
212  };
213 
220 
221  template <typename U>
223  {
224  assert(!builtins[builtin].ptr);
225 
226  builtins[builtin].ptr = (void **)&value.ptr;
227  builtins[builtin].size = sizeof(*value.ptr) * U::ArraySize;
228  }
229 
231  {
232  assert(builtins[builtin].ptr);
233  assert(size >= builtins[builtin].size);
234 
235  *builtins[builtin].ptr = data;
236  }
237 
238  template <typename U>
239  void register_resource(const internal::Resource<U> &value, unsigned set, unsigned binding)
240  {
241  assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS);
242  assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS);
243  assert(!resources[set][binding].ptr);
244 
245  resources[set][binding].ptr = (void **)&value.ptr;
248  }
249 
250  template <typename U>
252  {
254  assert(!stage_inputs[location].ptr);
255 
256  stage_inputs[location].ptr = (void **)&value.ptr;
258  }
259 
260  template <typename U>
262  {
264  assert(!stage_outputs[location].ptr);
265 
266  stage_outputs[location].ptr = (void **)&value.ptr;
268  }
269 
270  template <typename U>
272  {
274  assert(!uniform_constants[location].ptr);
275 
276  uniform_constants[location].ptr = (void **)&value.ptr;
278  }
279 
280  template <typename U>
282  {
283  assert(!push_constant.ptr);
284 
285  push_constant.ptr = (void **)&value.ptr;
287  }
288 
289  void set_stage_input(unsigned location, void *data, size_t size)
290  {
292  assert(stage_inputs[location].ptr);
293  assert(size >= stage_inputs[location].size);
294 
296  }
297 
298  void set_stage_output(unsigned location, void *data, size_t size)
299  {
301  assert(stage_outputs[location].ptr);
302  assert(size >= stage_outputs[location].size);
303 
305  }
306 
307  void set_uniform_constant(unsigned location, void *data, size_t size)
308  {
310  assert(uniform_constants[location].ptr);
311  assert(size >= uniform_constants[location].size);
312 
314  }
315 
316  void set_push_constant(void *data, size_t size)
317  {
318  assert(push_constant.ptr);
319  assert(size >= push_constant.size);
320 
322  }
323 
324  void set_resource(unsigned set, unsigned binding, void **data, size_t size)
325  {
326  assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS);
327  assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS);
328  assert(resources[set][binding].ptr);
329  assert(size >= resources[set][binding].size);
330 
331  // We're using the regular PointerInterface, dereference ahead of time.
332  if (resources[set][binding].pre_dereference)
333  *resources[set][binding].ptr = *data;
334  else
335  *resources[set][binding].ptr = data;
336  }
337 };
338 
339 namespace spirv_cross
340 {
341 template <typename T>
343 {
344  void invoke()
345  {
346  static_cast<T *>(this)->main();
347  }
348 };
349 
351 {
354  {
355  s.register_builtin(SPIRV_CROSS_BUILTIN_FRAG_COORD, gl_FragCoord);
356  }
357 #define gl_FragCoord __res->gl_FragCoord.get()
358 };
359 
360 template <typename T, typename Res>
361 struct FragmentShader : BaseShader<FragmentShader<T, Res>>
362 {
363  inline void main()
364  {
365  impl.main();
366  }
367 
369  {
370  resources.init(*this);
371  impl.__res = &resources;
372  }
373 
376 };
377 
379 {
382  {
383  s.register_builtin(SPIRV_CROSS_BUILTIN_POSITION, gl_Position);
384  }
385 #define gl_Position __res->gl_Position.get()
386 };
387 
388 template <typename T, typename Res>
389 struct VertexShader : BaseShader<VertexShader<T, Res>>
390 {
391  inline void main()
392  {
393  impl.main();
394  }
395 
397  {
398  resources.init(*this);
399  impl.__res = &resources;
400  }
401 
404 };
405 
407 {
408  inline void init(spirv_cross_shader &)
409  {
410  }
411 };
412 
413 template <typename T, typename Res>
414 struct TessEvaluationShader : BaseShader<TessEvaluationShader<T, Res>>
415 {
416  inline void main()
417  {
418  impl.main();
419  }
420 
422  {
423  resources.init(*this);
424  impl.__res = &resources;
425  }
426 
429 };
430 
432 {
433  inline void init(spirv_cross_shader &)
434  {
435  }
436 };
437 
438 template <typename T, typename Res>
439 struct TessControlShader : BaseShader<TessControlShader<T, Res>>
440 {
441  inline void main()
442  {
443  impl.main();
444  }
445 
447  {
448  resources.init(*this);
449  impl.__res = &resources;
450  }
451 
454 };
455 
457 {
458  inline void init(spirv_cross_shader &)
459  {
460  }
461 };
462 
463 template <typename T, typename Res>
464 struct GeometryShader : BaseShader<GeometryShader<T, Res>>
465 {
466  inline void main()
467  {
468  impl.main();
469  }
470 
472  {
473  resources.init(*this);
474  impl.__res = &resources;
475  }
476 
479 };
480 
482 {
486  {
489  }
490 #define gl_WorkGroupID __res->gl_WorkGroupID__.get()
491 #define gl_NumWorkGroups __res->gl_NumWorkGroups__.get()
492 
494 #define barrier() __res->barrier__.wait()
495 };
496 
498 {
500 #define gl_LocalInvocationIndex __priv_res.gl_LocalInvocationIndex__
502 #define gl_LocalInvocationID __priv_res.gl_LocalInvocationID__
504 #define gl_GlobalInvocationID __priv_res.gl_GlobalInvocationID__
505 };
506 
507 template <typename T, typename Res, unsigned WorkGroupX, unsigned WorkGroupY, unsigned WorkGroupZ>
508 struct ComputeShader : BaseShader<ComputeShader<T, Res, WorkGroupX, WorkGroupY, WorkGroupZ>>
509 {
510  inline void main()
511  {
512  resources.barrier__.reset_counter();
513 
514  for (unsigned z = 0; z < WorkGroupZ; z++)
515  for (unsigned y = 0; y < WorkGroupY; y++)
516  for (unsigned x = 0; x < WorkGroupX; x++)
517  impl[z][y][x].__priv_res.gl_GlobalInvocationID__ =
518  glm::uvec3(WorkGroupX, WorkGroupY, WorkGroupZ) * resources.gl_WorkGroupID__.get() +
519  glm::uvec3(x, y, z);
520 
521  group.run();
522  group.wait();
523  }
524 
526  : group(&impl[0][0][0])
527  {
528  resources.init(*this);
529  resources.barrier__.set_release_divisor(WorkGroupX * WorkGroupY * WorkGroupZ);
530 
531  unsigned i = 0;
532  for (unsigned z = 0; z < WorkGroupZ; z++)
533  {
534  for (unsigned y = 0; y < WorkGroupY; y++)
535  {
536  for (unsigned x = 0; x < WorkGroupX; x++)
537  {
538  impl[z][y][x].__priv_res.gl_LocalInvocationID__ = glm::uvec3(x, y, z);
539  impl[z][y][x].__priv_res.gl_LocalInvocationIndex__ = i++;
540  impl[z][y][x].__res = &resources;
541  }
542  }
543  }
544  }
545 
546  T impl[WorkGroupZ][WorkGroupY][WorkGroupX];
549 };
550 
551 inline void memoryBarrierShared()
552 {
554 }
555 inline void memoryBarrier()
556 {
558 }
559 // TODO: Rest of the barriers.
560 
561 // Atomics
562 template <typename T>
563 inline T atomicAdd(T &v, T a)
564 {
565  static_assert(sizeof(std::atomic<T>) == sizeof(T), "Cannot cast properly to std::atomic<T>.");
566 
567  // We need explicit memory barriers in GLSL to enfore any ordering.
568  // FIXME: Can we really cast this? There is no other way I think ...
569  return std::atomic_fetch_add_explicit(reinterpret_cast<std::atomic<T> *>(&v), a, std::memory_order_relaxed);
570 }
571 }
572 
574 {
575  shader->set_stage_input(location, data, size);
576 }
577 
579 {
580  shader->set_stage_output(location, data, size);
581 }
582 
584 {
585  shader->set_uniform_constant(location, data, size);
586 }
587 
588 void spirv_cross_set_resource(spirv_cross_shader_t *shader, unsigned set, unsigned binding, void **data, size_t size)
589 {
590  shader->set_resource(set, binding, data, size);
591 }
592 
594 {
595  shader->set_push_constant(data, size);
596 }
597 
599 {
600  shader->set_builtin(builtin, data, size);
601 }
602 
603 #endif
GLuint shader
Definition: glext.h:6670
Definition: internal_interface.hpp:481
PPSize()
Definition: internal_interface.hpp:192
const GLvoid * ptr
Definition: nx_glsym.h:242
Definition: internal_interface.hpp:439
T * ptr
Definition: internal_interface.hpp:88
Definition: internal_interface.hpp:406
void spirv_cross_set_stage_input(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:573
Res resources
Definition: internal_interface.hpp:428
Definition: internal_interface.hpp:175
size_t size
Definition: internal_interface.hpp:210
void register_resource(const internal::Resource< U > &value, unsigned set, unsigned binding)
Definition: internal_interface.hpp:239
Res resources
Definition: internal_interface.hpp:403
#define T(x)
#define SPIRV_CROSS_NUM_STAGE_OUTPUTS
Definition: external_interface.h:60
Definition: internal_interface.hpp:508
FragmentShader()
Definition: internal_interface.hpp:368
#define SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS
Definition: external_interface.h:58
Definition: internal_interface.hpp:464
void register_push_constant(const internal::PushConstant< U > &value)
Definition: internal_interface.hpp:281
T impl
Definition: internal_interface.hpp:452
Barrier barrier__
Definition: internal_interface.hpp:493
glm::uvec3 gl_LocalInvocationID__
Definition: internal_interface.hpp:501
GLsizeiptr size
Definition: glext.h:6559
internal::StageInput< glm::uvec3 > gl_WorkGroupID__
Definition: internal_interface.hpp:483
void set_resource(unsigned set, unsigned binding, void **data, size_t size)
Definition: internal_interface.hpp:324
VertexShader()
Definition: internal_interface.hpp:396
internal::StageOutput< glm::vec4 > gl_Position
Definition: internal_interface.hpp:380
Definition: internal_interface.hpp:171
Definition: external_interface.h:48
void main()
Definition: internal_interface.hpp:391
Definition: external_interface.h:49
Res resources
Definition: internal_interface.hpp:375
GLdouble s
Definition: glext.h:6390
Definition: internal_interface.hpp:121
T & operator[](unsigned index) const
Definition: internal_interface.hpp:127
GLdouble GLdouble z
Definition: glext.h:6514
void set_push_constant(void *data, size_t size)
Definition: internal_interface.hpp:316
spirv_cross_builtin
Definition: external_interface.h:47
ComputeShader()
Definition: internal_interface.hpp:525
Definition: ibxm.h:9
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:6303
PPSize push_constant
Definition: internal_interface.hpp:218
void register_stage_input(const internal::StageInput< U > &value, unsigned location)
Definition: internal_interface.hpp:251
GLint location
Definition: glext.h:6690
void set_uniform_constant(unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:307
glm::uvec3 gl_GlobalInvocationID__
Definition: internal_interface.hpp:503
DereferenceAdaptor(T **ptr)
Definition: internal_interface.hpp:123
T impl
Definition: internal_interface.hpp:402
internal::StageInput< glm::uvec3 > gl_NumWorkGroups__
Definition: internal_interface.hpp:484
Definition: internal_interface.hpp:98
Res resources
Definition: internal_interface.hpp:548
void main()
Definition: internal_interface.hpp:416
void init(spirv_cross_shader &)
Definition: internal_interface.hpp:433
T impl[WorkGroupZ][WorkGroupY][WorkGroupX]
Definition: internal_interface.hpp:546
internal::StageOutput< glm::vec4 > gl_FragCoord
Definition: internal_interface.hpp:352
T impl
Definition: internal_interface.hpp:477
void spirv_cross_set_builtin(spirv_cross_shader_t *shader, spirv_cross_builtin builtin, void *data, size_t size)
Definition: internal_interface.hpp:598
void set_stage_input(unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:289
void spirv_cross_set_push_constant(spirv_cross_shader_t *shader, void *data, size_t size)
Definition: internal_interface.hpp:593
Definition: barrier.hpp:23
Definition: internal_interface.hpp:188
PointerInterface()
Definition: internal_interface.hpp:148
#define SPIRV_CROSS_NUM_UNIFORM_CONSTANTS
Definition: external_interface.h:61
void init(spirv_cross_shader &s)
Definition: internal_interface.hpp:381
Definition: external_interface.h:52
T ** ptr
Definition: internal_interface.hpp:131
bool pre_dereference
Definition: internal_interface.hpp:211
void init(spirv_cross_shader &s)
Definition: internal_interface.hpp:353
Definition: internal_interface.hpp:361
void register_builtin(spirv_cross_builtin builtin, const U &value)
Definition: internal_interface.hpp:222
T atomicAdd(T &v, T a)
Definition: internal_interface.hpp:563
GLint GLint GLint GLint GLint GLint y
Definition: glext.h:6295
#define SPIRV_CROSS_NUM_DESCRIPTOR_SETS
Definition: external_interface.h:57
T * get()
Definition: internal_interface.hpp:82
GLint GLint GLint GLint GLint x
Definition: glext.h:6295
void ** ptr
Definition: internal_interface.hpp:197
void main()
Definition: internal_interface.hpp:441
Definition: document.h:391
T impl
Definition: internal_interface.hpp:427
void main()
Definition: internal_interface.hpp:510
GeometryShader()
Definition: internal_interface.hpp:471
Res resources
Definition: internal_interface.hpp:453
Definition: barrier.hpp:25
size_t size
Definition: internal_interface.hpp:198
void spirv_cross_set_uniform_constant(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:583
Definition: internal_interface.hpp:431
PPSize uniform_constants[SPIRV_CROSS_NUM_UNIFORM_CONSTANTS]
Definition: internal_interface.hpp:217
void set_stage_output(unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:298
Interface()
Definition: internal_interface.hpp:55
GLuint index
Definition: glext.h:6671
ThreadGroup< T, WorkGroupX *WorkGroupY *WorkGroupZ > group
Definition: internal_interface.hpp:547
PPSize stage_inputs[SPIRV_CROSS_NUM_STAGE_INPUTS]
Definition: internal_interface.hpp:215
int main(int argc, char *argv[])
Definition: send-presence.c:197
const GLdouble * v
Definition: glext.h:6391
Definition: internal_interface.hpp:201
void memoryBarrierShared()
Definition: internal_interface.hpp:551
Definition: internal_interface.hpp:52
Definition: internal_interface.hpp:47
Definition: internal_interface.hpp:497
Definition: internal_interface.hpp:183
PPSize builtins[SPIRV_CROSS_NUM_BUILTINS]
Definition: internal_interface.hpp:219
void invoke()
Definition: internal_interface.hpp:344
void main()
Definition: internal_interface.hpp:466
void init(spirv_cross_shader &)
Definition: internal_interface.hpp:408
#define SPIRV_CROSS_NUM_STAGE_INPUTS
Definition: external_interface.h:59
GLboolean GLuint group
Definition: glext.h:12027
void memoryBarrier()
Definition: internal_interface.hpp:555
DereferenceAdaptor< T > get()
Definition: internal_interface.hpp:153
void init(spirv_cross_shader &s)
Definition: internal_interface.hpp:485
void set_builtin(spirv_cross_builtin builtin, void *data, size_t size)
Definition: internal_interface.hpp:230
Definition: external_interface.h:50
Definition: external_interface.h:51
T & get()
Definition: internal_interface.hpp:59
Definition: internal_interface.hpp:389
void main()
Definition: internal_interface.hpp:363
Definition: internal_interface.hpp:165
Res resources
Definition: internal_interface.hpp:478
Interface()
Definition: internal_interface.hpp:78
GLsizei const GLfloat * value
Definition: glext.h:6709
Definition: internal_interface.hpp:350
void register_stage_output(const internal::StageOutput< U > &value, unsigned location)
Definition: internal_interface.hpp:261
Unknown compiler Device disconnected from port File already exists Saving to backup buffer Got connection No arguments supplied and no menu builtin
Definition: msg_hash_eo.h:34
void spirv_cross_set_resource(spirv_cross_shader_t *shader, unsigned set, unsigned binding, void **data, size_t size)
Definition: internal_interface.hpp:588
Definition: internal_interface.hpp:190
PPSize stage_outputs[SPIRV_CROSS_NUM_STAGE_OUTPUTS]
Definition: internal_interface.hpp:216
void init(spirv_cross_shader &)
Definition: internal_interface.hpp:458
Definition: internal_interface.hpp:179
#define false
Definition: ordinals.h:83
void spirv_cross_set_stage_output(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size)
Definition: internal_interface.hpp:578
Definition: internal_interface.hpp:51
Definition: internal_interface.hpp:456
TessControlShader()
Definition: internal_interface.hpp:446
T & get()
Definition: internal_interface.hpp:110
Definition: internal_interface.hpp:97
Definition: internal_interface.hpp:102
Definition: internal_interface.hpp:414
void register_uniform_constant(const internal::UniformConstant< U > &value, unsigned location)
Definition: internal_interface.hpp:271
T * ptr
Definition: internal_interface.hpp:65
T * ptr
Definition: internal_interface.hpp:116
unsigned int uint32_t
Definition: stdint.h:126
Definition: internal_interface.hpp:378
PointerInterface()
Definition: internal_interface.hpp:105
PPSizeResource resources[SPIRV_CROSS_NUM_DESCRIPTOR_SETS][SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS]
Definition: internal_interface.hpp:214
TessEvaluationShader()
Definition: internal_interface.hpp:421
Definition: internal_interface.hpp:342
PPSizeResource()
Definition: internal_interface.hpp:203
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6844
void ** ptr
Definition: internal_interface.hpp:209
uint32_t gl_LocalInvocationIndex__
Definition: internal_interface.hpp:499
T ** ptr
Definition: internal_interface.hpp:159
Definition: internal_interface.hpp:93
static void memoryBarrier()
Definition: barrier.hpp:39
T impl
Definition: internal_interface.hpp:374