1 | #ifndef SHADER_H |
1 | #ifndef SHADER_H |
2 | #define SHADER_H |
2 | #define SHADER_H |
3 | |
3 | |
4 | #include <cassert> |
4 | #include <cassert> |
5 | |
5 | |
|
|
6 | #include <set> |
6 | #include <map> |
7 | #include <map> |
7 | #include <sstream> |
8 | #include <sstream> |
8 | |
9 | |
9 | #include "opengl.h" |
10 | #include "opengl.h" |
10 | #include "util.h" |
11 | #include "util.h" |
… | |
… | |
13 | |
14 | |
14 | using namespace std; |
15 | using namespace std; |
15 | |
16 | |
16 | const int NAMELEN = 32; |
17 | const int NAMELEN = 32; |
17 | |
18 | |
|
|
19 | namespace compile { |
|
|
20 | struct shader_builder |
|
|
21 | { |
|
|
22 | set<const void *> seen; |
|
|
23 | |
|
|
24 | ostringstream global; |
|
|
25 | ostringstream local; |
|
|
26 | ostringstream code; |
|
|
27 | |
|
|
28 | bool first (const void *p); |
|
|
29 | }; |
|
|
30 | |
|
|
31 | extern shader_builder *cur; |
|
|
32 | } |
|
|
33 | |
18 | template<class T> |
34 | template<class T> |
19 | struct sl_expr { |
35 | struct sl_expr { |
20 | const T t; |
36 | const T &t; |
21 | sl_expr (const T &t) : t(t) { } |
37 | sl_expr (const T &t) : t(t) { } |
22 | void operator ()() const { t (); } |
38 | void operator ()() const { t (); } |
23 | template<typename expr> |
39 | template<typename expr> |
24 | const sl_expr &operator =(const expr &e) const; |
40 | const sl_expr &operator =(const expr &e) const; |
25 | }; |
41 | }; |
… | |
… | |
50 | |
66 | |
51 | struct sl_func0 |
67 | struct sl_func0 |
52 | { |
68 | { |
53 | const char *name_par; |
69 | const char *name_par; |
54 | sl_func0 (const char *name_par) : name_par(name_par) { } |
70 | sl_func0 (const char *name_par) : name_par(name_par) { } |
|
|
71 | |
55 | void begin () const; |
72 | void begin () const |
|
|
73 | { |
|
|
74 | compile::cur->code << name_par; |
|
|
75 | } |
|
|
76 | |
56 | void comma () const; |
77 | void comma () const |
|
|
78 | { |
|
|
79 | compile::cur->code << ", "; |
|
|
80 | } |
|
|
81 | |
57 | void end () const; |
82 | void end () const |
|
|
83 | { |
|
|
84 | compile::cur->code << ")"; |
|
|
85 | } |
|
|
86 | |
58 | void operator ()() const |
87 | void operator ()() const |
59 | { |
88 | { |
60 | begin (); |
89 | begin (); |
61 | end (); |
90 | end (); |
62 | } |
91 | } |
… | |
… | |
95 | }; |
124 | }; |
96 | |
125 | |
97 | class refcounted |
126 | class refcounted |
98 | { |
127 | { |
99 | template<class type> friend class ref; |
128 | template<class type> friend class ref; |
100 | mutable int refcnt; |
129 | mutable unsigned int refcnt; |
101 | void refcnt_inc () const { refcnt++; } |
130 | void refcnt_inc () const { refcnt++; } |
|
|
131 | void refcnt_dec () const { if (!--refcnt) refcnt_destroy (); } |
102 | void refcnt_dec () const; |
132 | void refcnt_destroy () const; |
103 | public: |
133 | public: |
104 | refcounted () : refcnt(0) { } |
134 | refcounted () : refcnt(0) { } |
105 | virtual ~refcounted (); |
135 | virtual ~refcounted (); |
106 | }; |
136 | }; |
107 | |
137 | |
… | |
… | |
207 | extern const char str_sampler_cube []; |
237 | extern const char str_sampler_cube []; |
208 | |
238 | |
209 | typedef ref<struct var_i> var; |
239 | typedef ref<struct var_i> var; |
210 | typedef ref<struct uniform_i> uniform; |
240 | typedef ref<struct uniform_i> uniform; |
211 | |
241 | |
212 | struct shader_builder |
|
|
213 | { |
|
|
214 | vector<var> refs; // uniform/varying parameters |
|
|
215 | vector<var> temps; // temporary variables |
|
|
216 | |
|
|
217 | ostringstream source; |
|
|
218 | |
|
|
219 | template<typename type> |
|
|
220 | shader_builder &operator <<(const type &t) |
|
|
221 | { |
|
|
222 | source << t; |
|
|
223 | return *this; |
|
|
224 | } |
|
|
225 | }; |
|
|
226 | |
|
|
227 | struct fragment_i : refcounted |
242 | struct fragment_i : refcounted |
228 | { |
243 | { |
229 | virtual void build (shader_builder &b) = 0; |
|
|
230 | }; |
244 | }; |
231 | |
245 | |
232 | typedef ref<fragment_i> fragment; |
246 | typedef ref<fragment_i> fragment; |
233 | |
247 | |
234 | struct lvalue_i : fragment_i |
248 | struct lvalue_i : fragment_i |
… | |
… | |
237 | |
251 | |
238 | // a simple predeclared variable with unspecified type |
252 | // a simple predeclared variable with unspecified type |
239 | struct gluvar_i : lvalue_i |
253 | struct gluvar_i : lvalue_i |
240 | { |
254 | { |
241 | const char *name; |
255 | const char *name; |
242 | void build (shader_builder &b); |
256 | |
|
|
257 | void operator ()() const |
|
|
258 | { |
|
|
259 | compile::cur->code << name; |
|
|
260 | } |
|
|
261 | |
243 | gluvar_i (const char *name) : name (name) { } |
262 | gluvar_i (const char *name) : name (name) { } |
244 | }; |
263 | }; |
245 | |
264 | |
246 | typedef auto_lvalue_ref1<gluvar_i, const char *> gluvar; |
265 | typedef auto_lvalue_ref1<gluvar_i, const char *> gluvar; |
247 | |
266 | |
248 | struct var_i : lvalue_i |
267 | struct var_i : lvalue_i |
249 | { |
268 | { |
250 | static unsigned int next_id; |
269 | static unsigned int next_id; |
251 | |
270 | |
252 | char name[NAMELEN]; |
271 | char name[NAMELEN]; |
|
|
272 | const char *domainstr; |
253 | const char *typestr; |
273 | const char *typestr; |
254 | |
274 | |
255 | void build (shader_builder &b); |
275 | void operator ()() const; |
256 | virtual void build_decl (ostringstream &b); |
276 | |
257 | |
277 | var_i (const char *domainstr, const char *typestr); |
258 | var_i (const char *typestr); |
|
|
259 | ~var_i (); |
278 | ~var_i (); |
260 | }; |
279 | }; |
261 | |
280 | |
262 | struct uniform_i : var_i |
281 | struct uniform_i : var_i |
263 | { |
282 | { |
264 | void build (shader_builder &b); |
|
|
265 | void build_decl (ostringstream &b); |
|
|
266 | |
|
|
267 | GLint location (); |
283 | GLint location (); |
268 | |
284 | |
269 | uniform_i (const char *strtype); |
285 | uniform_i (const char *strtype); |
270 | }; |
286 | }; |
271 | |
287 | |
… | |
… | |
396 | #if 0 |
412 | #if 0 |
397 | // to be used for attributes |
413 | // to be used for attributes |
398 | |
414 | |
399 | struct stream_i : var_i |
415 | struct stream_i : var_i |
400 | { |
416 | { |
401 | void build (shader_builder &b); |
|
|
402 | void build_decl (ostringstream &b); |
|
|
403 | stream_i (const char *strtype); |
417 | stream_i (const char *strtype); |
404 | }; |
418 | }; |
405 | |
419 | |
406 | template<int dimension, GLenum gltype, const char *strtype> |
420 | template<int dimension, GLenum gltype, const char *strtype> |
407 | struct varying_i : stream_i |
421 | struct varying_i : stream_i |
… | |
… | |
458 | typedef var_ref<varying_4f_i> varying_4f; |
472 | typedef var_ref<varying_4f_i> varying_4f; |
459 | #endif |
473 | #endif |
460 | |
474 | |
461 | struct varying_i : var_i |
475 | struct varying_i : var_i |
462 | { |
476 | { |
463 | void build_decl (ostringstream &b); |
|
|
464 | void build (shader_builder &b); |
|
|
465 | varying_i (const char *strtype); |
477 | varying_i (const char *strtype); |
466 | }; |
478 | }; |
467 | |
479 | |
468 | struct temporary_i : var_i |
480 | struct temporary_i : var_i |
469 | { |
481 | { |
470 | void build (shader_builder &b); |
|
|
471 | temporary_i (const char *strtype); |
482 | temporary_i (const char *strtype); |
472 | }; |
483 | }; |
473 | |
484 | |
474 | template<const char *strtype, class var_i> |
485 | template<const char *strtype, class var_i> |
475 | struct glnvar_ref : ref<var_i> |
486 | struct glnvar_ref : ref<var_i> |
… | |
… | |
640 | typedef sampler_ref<sampler_2d_rect_shadow_i> sampler_2d_rect_shadow; |
651 | typedef sampler_ref<sampler_2d_rect_shadow_i> sampler_2d_rect_shadow; |
641 | typedef sampler_ref<sampler_3d_i> sampler_3d; |
652 | typedef sampler_ref<sampler_3d_i> sampler_3d; |
642 | typedef sampler_ref<sampler_3d_rect_i> sampler_3d_rect; |
653 | typedef sampler_ref<sampler_3d_rect_i> sampler_3d_rect; |
643 | typedef sampler_ref<sampler_cube_i> sampler_cube; |
654 | typedef sampler_ref<sampler_cube_i> sampler_cube; |
644 | |
655 | |
645 | struct fragment_const_string_i : fragment_i |
|
|
646 | { |
|
|
647 | const char *str; |
|
|
648 | |
|
|
649 | void build (shader_builder &b); |
|
|
650 | |
|
|
651 | fragment_const_string_i (const char *str) : str(str) { } |
|
|
652 | }; |
|
|
653 | |
|
|
654 | typedef auto_ref1<fragment_const_string_i, const char *> fragment_const_string; |
|
|
655 | |
|
|
656 | struct fragment_string_i : fragment_i |
|
|
657 | { |
|
|
658 | char *str; |
|
|
659 | |
|
|
660 | void build (shader_builder &b); |
|
|
661 | |
|
|
662 | fragment_string_i (const char *str) : str (strdup (str)) { } |
|
|
663 | ~fragment_string_i (); |
|
|
664 | }; |
|
|
665 | |
|
|
666 | struct fragment_vector_i : fragment_i, vector<fragment> |
|
|
667 | { |
|
|
668 | void build (shader_builder &b); |
|
|
669 | |
|
|
670 | template<class fragment_i> |
|
|
671 | void append (const ref<fragment_i> &f) |
|
|
672 | { |
|
|
673 | push_back (f); |
|
|
674 | } |
|
|
675 | |
|
|
676 | template<class expr> |
|
|
677 | void append (const sl_expr<expr> &e) |
|
|
678 | { |
|
|
679 | e (); |
|
|
680 | } |
|
|
681 | |
|
|
682 | void append_const (const char *s) |
|
|
683 | { |
|
|
684 | push_back (*new fragment_const_string_i (s)); |
|
|
685 | } |
|
|
686 | |
|
|
687 | void append_string (const char *s) |
|
|
688 | { |
|
|
689 | push_back (*new fragment_string_i (s)); |
|
|
690 | } |
|
|
691 | }; |
|
|
692 | |
|
|
693 | typedef ref<fragment_vector_i> fragment_vector; |
|
|
694 | |
|
|
695 | struct shader_object_i : fragment_vector_i |
656 | struct shader_object_i : refcounted |
696 | { |
657 | { |
697 | GLenum type; |
658 | GLenum type; |
698 | GLuint id; // GLhandleARB, but 2.0 will use uint |
659 | GLuint id; // GLhandleARB, but 2.0 will use uint |
699 | |
660 | |
700 | string source (); |
|
|
701 | void compile (); |
|
|
702 | void start (); |
661 | void start (); |
703 | void stop (); |
662 | void stop (); |
704 | |
663 | |
705 | shader_object_i (GLenum type); |
664 | shader_object_i (GLenum type); |
706 | ~shader_object_i (); |
665 | ~shader_object_i (); |
707 | }; |
666 | }; |
708 | |
667 | |
709 | extern shader_object_i *cur; // record actions to this shader |
|
|
710 | |
|
|
711 | template<GLenum type> |
668 | template<GLenum type> |
712 | struct shader_object : ref<shader_object_i> |
669 | struct shader_object : ref<shader_object_i> |
713 | { |
670 | { |
714 | shader_object () |
671 | shader_object () |
715 | : ref<shader_object_i> (*new shader_object_i (type)) |
672 | : ref<shader_object_i> (*new shader_object_i (type)) |
… | |
… | |
738 | |
695 | |
739 | void enable (); |
696 | void enable (); |
740 | void disable (); |
697 | void disable (); |
741 | }; |
698 | }; |
742 | |
699 | |
743 | template<typename T> |
|
|
744 | struct sl_append |
|
|
745 | { |
|
|
746 | T t; |
|
|
747 | |
|
|
748 | sl_append (const T &t) : t(t) { } |
|
|
749 | |
|
|
750 | void operator ()() const |
|
|
751 | { |
|
|
752 | cur->push_back (t); |
|
|
753 | } |
|
|
754 | }; |
|
|
755 | |
|
|
756 | template<int length> |
700 | template<int length> |
757 | struct sl_string |
701 | struct sl_string |
758 | { |
702 | { |
759 | char str[length]; |
703 | char str[length]; |
760 | |
704 | |
761 | void operator ()() const |
705 | void operator ()() const |
762 | { |
706 | { |
763 | cur->push_back (*new fragment_string_i (str)); |
707 | compile::cur->code << str; |
764 | } |
708 | } |
765 | }; |
709 | }; |
766 | |
710 | |
767 | struct sl_float |
711 | struct sl_float |
768 | { |
712 | { |
769 | const GLfloat c; |
713 | const GLfloat c; |
770 | |
714 | |
771 | sl_float (GLfloat c) : c(c) { } |
715 | sl_float (GLfloat c) : c(c) { } |
772 | |
716 | |
773 | void operator ()() const; |
717 | void operator ()() const |
|
|
718 | { |
|
|
719 | compile::cur->code << c; |
|
|
720 | } |
774 | }; |
721 | }; |
775 | |
722 | |
776 | template<class A, class B> |
723 | template<class A, class B> |
777 | inline sl_expr< sl_concat2<A, B> > |
724 | inline sl_expr< sl_concat2<A, B> > |
778 | concat (const A &a, const B &b) |
725 | concat (const A &a, const B &b) |
… | |
… | |
838 | }; |
785 | }; |
839 | |
786 | |
840 | template<> |
787 | template<> |
841 | struct sl_convert<vec2> |
788 | struct sl_convert<vec2> |
842 | { |
789 | { |
843 | typedef sl_expr< sl_string<60> > T; |
|
|
844 | static const T convert (const vec2 &v); |
790 | static const sl_expr< sl_string<60> > convert (const vec2 &v); |
845 | }; |
791 | }; |
846 | |
792 | |
847 | template<> |
793 | template<> |
848 | struct sl_convert<vec3> |
794 | struct sl_convert<vec3> |
849 | { |
795 | { |
850 | typedef sl_expr< sl_string<80> > T; |
|
|
851 | static const T convert (const vec3 &v); |
796 | static const sl_expr< sl_string<80> > convert (const vec3 &v); |
852 | }; |
797 | }; |
853 | |
798 | |
854 | template<> |
799 | template<> |
855 | struct sl_convert<vec4> |
800 | struct sl_convert<vec4> |
856 | { |
801 | { |
857 | typedef sl_expr< sl_string<100> > T; |
|
|
858 | static const T convert (const vec4 &v); |
802 | static const sl_expr< sl_string<100> > convert (const vec4 &v); |
859 | }; |
803 | }; |
860 | |
804 | |
861 | template<> |
805 | template<> |
862 | template<class V> |
806 | template<class var_i> |
863 | struct sl_convert< var_ref<V> > |
807 | struct sl_convert< var_ref<var_i> > |
864 | { |
808 | { |
865 | typedef sl_expr< sl_append< var_ref<V> > > T; |
809 | typedef sl_expr< var_i > T; |
866 | static inline const T convert (const var_ref<V> &v) |
810 | static inline const T convert (const var_ref<var_i> &v) |
867 | { |
811 | { |
868 | return sl_append< var_ref<V> > (v); |
812 | return T (*&v); |
869 | } |
813 | } |
870 | }; |
814 | }; |
871 | |
815 | |
872 | template<> |
816 | template<> |
873 | struct sl_convert<gluvar> |
817 | template<class gluvar_i> |
|
|
818 | struct sl_convert< auto_lvalue_ref1<gluvar_i, const char *> > |
874 | { |
819 | { |
875 | typedef sl_expr< sl_append<gluvar> > T; |
820 | typedef sl_expr< gluvar_i > T; |
876 | static inline const T convert (const gluvar &v) |
821 | static inline const T convert (const auto_lvalue_ref1<gluvar_i, const char *> &v) |
877 | { |
822 | { |
878 | return sl_append<gluvar> (v); |
823 | return T (*&v); |
879 | } |
824 | } |
880 | }; |
825 | }; |
881 | |
826 | |
882 | template<> |
827 | template<> |
883 | template<const char *strtype, class var_i> |
828 | template<const char *strtype, class var_i> |
884 | struct sl_convert< glnvar_ref<strtype, var_i> > |
829 | struct sl_convert< glnvar_ref<strtype, var_i> > |
885 | { |
830 | { |
886 | typedef sl_expr< sl_append< glnvar_ref<strtype, var_i> > > T; |
831 | typedef sl_expr< var_i > T; |
887 | static inline const T convert (const glnvar_ref<strtype, var_i> &v) |
832 | static inline const T convert (const glnvar_ref<strtype, var_i> &v) |
888 | { |
833 | { |
889 | return sl_expr< sl_append< glnvar_ref<strtype, var_i> > >( |
834 | return T (*&v); |
890 | sl_append< glnvar_ref<strtype, var_i> > (v) |
|
|
891 | ); |
|
|
892 | } |
835 | } |
893 | }; |
836 | }; |
894 | |
837 | |
895 | template<> |
838 | template<> |
896 | template<class sampler_i> |
839 | template<class sampler_i> |
897 | struct sl_convert< sampler_ref<sampler_i> > |
840 | struct sl_convert< sampler_ref<sampler_i> > |
898 | { |
841 | { |
899 | typedef sl_expr< sl_append< sampler_ref<sampler_i> > > T; |
842 | typedef sl_expr< sampler_i > T; |
900 | static inline const T convert (const sampler_ref<sampler_i> &v) |
843 | static inline const T convert (const sampler_ref<sampler_i> &v) |
901 | { |
844 | { |
902 | return sl_append< sampler_ref<sampler_i> > (v); |
845 | return T (*&v); |
903 | } |
846 | } |
904 | }; |
847 | }; |
905 | |
848 | |
906 | namespace compile { |
849 | namespace compile { |
907 | extern const fragment_const_string str_2sp; |
|
|
908 | extern const fragment_const_string str_equal; |
|
|
909 | extern const fragment_const_string str_comma; |
|
|
910 | extern const fragment_const_string str_endl; |
|
|
911 | |
|
|
912 | template<class fragment, typename expr> |
850 | template<class lvalue, typename expr> |
913 | inline void sl_assign (const fragment &f, const expr &e) |
851 | inline void sl_assign (const lvalue &l, const expr &e) |
914 | { |
852 | { |
915 | cur->append (str_2sp); |
853 | compile::cur->code << " "; |
916 | cur->append (f); |
854 | sl_convert<lvalue>::convert (l) (); |
917 | cur->append (str_equal); |
855 | compile::cur->code << " = "; |
918 | sl_convert<expr>::convert (e) (); |
856 | sl_convert<expr>::convert (e) (); |
919 | cur->append (str_endl); |
857 | compile::cur->code << ";\n"; |
920 | } |
858 | } |
921 | } |
859 | } |
922 | |
860 | |
923 | template<class type> |
861 | template<class type> |
924 | template<typename expr> |
862 | template<typename expr> |
… | |
… | |
949 | inline const glnvar_ref<strtype, var_i> &glnvar_ref<strtype, var_i>::operator =(const expr &e) const |
887 | inline const glnvar_ref<strtype, var_i> &glnvar_ref<strtype, var_i>::operator =(const expr &e) const |
950 | { |
888 | { |
951 | compile::sl_assign (*this, e); |
889 | compile::sl_assign (*this, e); |
952 | return *this; |
890 | return *this; |
953 | } |
891 | } |
954 | |
|
|
955 | struct sl_append_const_string |
|
|
956 | { |
|
|
957 | fragment_const_string str; |
|
|
958 | sl_append_const_string (const char *s) |
|
|
959 | : str (s) |
|
|
960 | { } |
|
|
961 | |
|
|
962 | void operator ()() const |
|
|
963 | { |
|
|
964 | cur->push_back (str); |
|
|
965 | } |
|
|
966 | }; |
|
|
967 | |
892 | |
968 | namespace compile { |
893 | namespace compile { |
969 | using namespace shader; |
894 | using namespace shader; |
970 | |
895 | |
971 | template<typename T> |
896 | template<typename T> |
… | |
… | |
987 | { |
912 | { |
988 | const A a; const char *b; const C c; |
913 | const A a; const char *b; const C c; |
989 | sl_binop (const A &a, const char *b, const C &c) : a(a), b(b), c(c) { } |
914 | sl_binop (const A &a, const char *b, const C &c) : a(a), b(b), c(c) { } |
990 | void operator ()() const |
915 | void operator ()() const |
991 | { |
916 | { |
992 | shader::cur->append_const ("("); |
917 | compile::cur->code << "("; |
993 | a (); |
918 | a (); |
994 | shader::cur->append_const (b); |
919 | compile::cur->code << b; |
995 | c (); |
920 | c (); |
996 | shader::cur->append_const (")"); |
921 | compile::cur->code << ")"; |
997 | } |
922 | } |
998 | }; |
923 | }; |
999 | |
924 | |
1000 | template<class A, class B, class C> |
925 | template<class A, class B, class C> |
1001 | struct sl_ternary |
926 | struct sl_ternary |
1002 | { |
927 | { |
1003 | const A a; const B b; const C c; |
928 | const A a; const B b; const C c; |
1004 | sl_ternary (const A &a, const B &b, const C &c) : a(a), b(b), c(c) { } |
929 | sl_ternary (const A &a, const B &b, const C &c) : a(a), b(b), c(c) { } |
1005 | void operator ()() const |
930 | void operator ()() const |
1006 | { |
931 | { |
1007 | shader::cur->append_const ("("); |
932 | compile::cur->code << "("; |
1008 | a (); |
933 | a (); |
1009 | shader::cur->append_const (") ? ("); |
934 | compile::cur->code << ") ? ("; |
1010 | b (); |
935 | b (); |
1011 | shader::cur->append_const (") : ("); |
936 | compile::cur->code << ") : ("; |
1012 | c (); |
937 | c (); |
1013 | shader::cur->append_const (")"); |
938 | compile::cur->code << ")"; |
1014 | } |
939 | } |
1015 | }; |
940 | }; |
1016 | |
941 | |
1017 | # define SHADER_BINOP(op) \ |
942 | # define SHADER_BINOP(op) \ |
1018 | template<typename A, typename B> \ |
943 | template<typename A, typename B> \ |
… | |
… | |
1045 | const A a; |
970 | const A a; |
1046 | const char *swizzle; |
971 | const char *swizzle; |
1047 | sl_swizzle (const A &a, const char *swizzle) : a(a), swizzle(swizzle) { } |
972 | sl_swizzle (const A &a, const char *swizzle) : a(a), swizzle(swizzle) { } |
1048 | void operator ()() const |
973 | void operator ()() const |
1049 | { |
974 | { |
1050 | shader::cur->append_const ("("); |
975 | compile::cur->code << "("; |
1051 | a (); |
976 | a (); |
1052 | shader::cur->append_const (")."); |
977 | compile::cur->code << ")." << swizzle; |
1053 | shader::cur->append_const (swizzle); |
|
|
1054 | } |
978 | } |
1055 | }; |
979 | }; |
1056 | |
980 | |
1057 | # define SHADER_SWIZZLE_OP(type) \ |
981 | # define SHADER_SWIZZLE_OP(type) \ |
1058 | template<typename T> \ |
982 | template<typename T> \ |