33 using std::ostringstream;
40 int Shader::_shaders_generated;
43 CGcontext Shader::_cg_context = 0;
60 string dstr =
"unknown ";
61 if (p._direction == SAD_in) {
63 }
else if (p._direction == SAD_out) {
65 }
else if (p._direction == SAD_inout) {
69 string tstr =
"invalid ";
71 case SAT_scalar: tstr =
"scalar ";
break;
72 case SAT_vec1: tstr =
"vec1 ";
break;
73 case SAT_vec2: tstr =
"vec2 ";
break;
74 case SAT_vec3: tstr =
"vec3 ";
break;
75 case SAT_vec4: tstr =
"vec4 ";
break;
76 case SAT_mat1x1: tstr =
"mat1x1 ";
break;
77 case SAT_mat1x2: tstr =
"mat1x2 ";
break;
78 case SAT_mat1x3: tstr =
"mat1x3 ";
break;
79 case SAT_mat1x4: tstr =
"mat1x4 ";
break;
80 case SAT_mat2x1: tstr =
"mat2x1 ";
break;
81 case SAT_mat2x2: tstr =
"mat2x2 ";
break;
82 case SAT_mat2x3: tstr =
"mat2x3 ";
break;
83 case SAT_mat2x4: tstr =
"mat2x4 ";
break;
84 case SAT_mat3x1: tstr =
"mat3x1 ";
break;
85 case SAT_mat3x2: tstr =
"mat3x2 ";
break;
86 case SAT_mat3x3: tstr =
"mat3x3 ";
break;
87 case SAT_mat3x4: tstr =
"mat3x4 ";
break;
88 case SAT_mat4x1: tstr =
"mat4x1 ";
break;
89 case SAT_mat4x2: tstr =
"mat4x2 ";
break;
90 case SAT_mat4x3: tstr =
"mat4x3 ";
break;
91 case SAT_mat4x4: tstr =
"mat4x4 ";
break;
92 case SAT_sampler1d: tstr =
"sampler1D ";
break;
93 case SAT_sampler2d: tstr =
"sampler2D ";
break;
94 case SAT_sampler3d: tstr =
"sampler3D ";
break;
95 case SAT_sampler2d_array: tstr =
"sampler2DArray ";
break;
96 case SAT_sampler_cube: tstr =
"samplerCUBE ";
break;
97 case SAT_sampler_buffer: tstr =
"samplerBUF ";
break;
98 case SAT_sampler_cube_array:tstr =
"samplerCUBEARRAY ";
break;
99 default: tstr =
"unknown ";
break;
102 string cstr =
"invalid";
104 case SAC_scalar: cstr =
"scalar ";
break;
105 case SAC_vector: cstr =
"vector ";
break;
106 case SAC_matrix: cstr =
"matrix ";
break;
107 case SAC_sampler: cstr =
"sampler ";
break;
108 case SAC_array: cstr =
"array ";
break;
109 default: cstr =
"unknown ";
break;
113 p._cat->
error() << fn <<
": " << vstr << dstr << tstr <<
114 p._id._name <<
": " << msg <<
"\n";
126 if ((
int)words.size() != len) {
140 if (p._direction != SAD_in) {
184 case SAT_scalar: nfloat = 1;
break;
185 case SAT_vec2: nfloat = 2;
break;
186 case SAT_vec3: nfloat = 3;
break;
187 case SAT_vec4: nfloat = 4;
break;
188 case SAT_mat3x3: nfloat = 9;
break;
189 case SAT_mat4x4: nfloat = 16;
break;
190 default: nfloat = 0;
break;
192 if ((nfloat < lo)||(nfloat > hi)) {
193 string msg =
"wrong type for parameter:";
204 cp_errchk_parameter_ptr(ShaderArgInfo &p) {
206 case SAC_scalar:
return true;
207 case SAC_vector:
return true;
208 case SAC_matrix:
return true;
210 switch (p._subclass) {
211 case SAC_scalar:
return true;
212 case SAC_vector:
return true;
213 case SAC_matrix:
return true;
215 string msg =
"unsupported array subclass.";
220 string msg =
"unsupported class.";
233 if ((p._type!=SAT_sampler1d)&&
234 (p._type!=SAT_sampler2d)&&
235 (p._type!=SAT_sampler3d)&&
236 (p._type!=SAT_sampler2d_array)&&
237 (p._type!=SAT_sampler_cube)&&
238 (p._type!=SAT_sampler_buffer)&&
239 (p._type!=SAT_sampler_cube_array)) {
251 if (words[next] !=
"") {
263 if ((words[next] !=
"to")&&(words[next] !=
"rel")) {
277 const string &nword = words[next];
278 if ((nword ==
"")||(nword ==
"to")||(nword ==
"rel")) {
291 vector_string &pieces,
int &next,
295 if (pieces[next] ==
"of") next++;
298 ShaderMatInput from_single;
299 ShaderMatInput from_double;
300 ShaderMatInput to_single;
301 ShaderMatInput to_double;
306 }
else if (word1 ==
"world") {
307 from_single = SMO_world_to_view;
308 from_double = SMO_INVALID;
309 to_single = SMO_view_to_world;
310 to_double = SMO_INVALID;
311 }
else if (word1 ==
"model") {
312 from_single = SMO_model_to_view;
313 from_double = SMO_view_x_to_view;
314 to_single = SMO_view_to_model;
315 to_double = SMO_view_to_view_x;
316 }
else if (word1 ==
"clip") {
317 from_single = SMO_clip_to_view;
318 from_double = SMO_clip_x_to_view;
319 to_single = SMO_view_to_clip;
320 to_double = SMO_view_to_clip_x;
321 }
else if (word1 ==
"view") {
322 from_single = SMO_identity;
323 from_double = SMO_view_x_to_view;
324 to_single = SMO_identity;
325 to_double = SMO_view_to_view_x;
326 }
else if (word1 ==
"apiview") {
327 from_single = SMO_apiview_to_view;
328 from_double = SMO_apiview_x_to_view;
329 to_single = SMO_view_to_apiview;
330 to_double = SMO_view_to_apiview_x;
331 }
else if (word1 ==
"apiclip") {
332 from_single = SMO_apiclip_to_view;
333 from_double = SMO_apiclip_x_to_view;
334 to_single = SMO_view_to_apiclip;
335 to_double = SMO_view_to_apiclip_x;
337 from_single = SMO_view_x_to_view;
338 from_double = SMO_view_x_to_view;
339 to_single = SMO_view_to_view_x;
340 to_double = SMO_view_to_view_x;
346 bind._part[0] = from_single;
347 bind._arg[0] =
nullptr;
349 if (from_double == SMO_INVALID) {
353 bind._part[0] = from_double;
354 bind._arg[0] = InternalName::make(word2);
358 bind._part[1] = to_single;
359 bind._arg[1] =
nullptr;
361 if (to_double == SMO_INVALID) {
365 bind._part[1] = to_double;
366 bind._arg[1] = InternalName::make(word2);
379 int dep = SSD_general;
381 if (inp == SMO_INVALID) {
384 if (inp == SMO_attr_material || inp == SMO_attr_material2) {
385 dep |= SSD_material | SSD_frame;
387 if (inp == SMO_attr_color) {
390 if (inp == SMO_attr_colorscale) {
391 dep |= SSD_colorscale;
393 if (inp == SMO_attr_fog || inp == SMO_attr_fogcolor) {
396 if ((inp == SMO_model_to_view) ||
397 (inp == SMO_view_to_model) ||
398 (inp == SMO_model_to_apiview) ||
399 (inp == SMO_apiview_to_model)) {
400 dep |= SSD_transform;
402 if ((inp == SMO_view_to_world) ||
403 (inp == SMO_world_to_view) ||
404 (inp == SMO_view_x_to_view) ||
405 (inp == SMO_view_to_view_x) ||
406 (inp == SMO_apiview_x_to_view) ||
407 (inp == SMO_view_to_apiview_x) ||
408 (inp == SMO_clip_x_to_view) ||
409 (inp == SMO_view_to_clip_x) ||
410 (inp == SMO_apiclip_x_to_view) ||
411 (inp == SMO_view_to_apiclip_x) ||
412 (inp == SMO_dlight_x) ||
413 (inp == SMO_plight_x) ||
414 (inp == SMO_slight_x)) {
415 dep |= SSD_view_transform;
417 if ((inp == SMO_texpad_x) ||
418 (inp == SMO_texpix_x) ||
419 (inp == SMO_alight_x) ||
420 (inp == SMO_dlight_x) ||
421 (inp == SMO_plight_x) ||
422 (inp == SMO_slight_x) ||
423 (inp == SMO_satten_x) ||
424 (inp == SMO_mat_constant_x) ||
425 (inp == SMO_vec_constant_x) ||
426 (inp == SMO_vec_constant_x_attrib) ||
427 (inp == SMO_view_x_to_view) ||
428 (inp == SMO_view_to_view_x) ||
429 (inp == SMO_apiview_x_to_view) ||
430 (inp == SMO_view_to_apiview_x) ||
431 (inp == SMO_clip_x_to_view) ||
432 (inp == SMO_view_to_clip_x) ||
433 (inp == SMO_apiclip_x_to_view) ||
434 (inp == SMO_view_to_apiclip_x)) {
435 dep |= SSD_shaderinputs;
437 if ((inp == SMO_texpad_x) ||
438 (inp == SMO_texpix_x) ||
439 (inp == SMO_alight_x) ||
440 (inp == SMO_dlight_x) ||
441 (inp == SMO_plight_x) ||
442 (inp == SMO_slight_x) ||
443 (inp == SMO_satten_x) ||
444 (inp == SMO_vec_constant_x_attrib) ||
445 (inp == SMO_view_x_to_view) ||
446 (inp == SMO_view_to_view_x) ||
447 (inp == SMO_apiview_x_to_view) ||
448 (inp == SMO_view_to_apiview_x) ||
449 (inp == SMO_clip_x_to_view) ||
450 (inp == SMO_view_to_clip_x) ||
451 (inp == SMO_apiclip_x_to_view) ||
452 (inp == SMO_view_to_apiclip_x)) {
458 if ((inp == SMO_light_ambient) ||
459 (inp == SMO_light_source_i_attrib) ||
460 (inp == SMO_light_source_i_packed)) {
461 dep |= SSD_light | SSD_frame;
462 if (inp == SMO_light_source_i_attrib ||
463 inp == SMO_light_source_i_packed) {
464 dep |= SSD_view_transform;
467 if ((inp == SMO_light_product_i_ambient) ||
468 (inp == SMO_light_product_i_diffuse) ||
469 (inp == SMO_light_product_i_specular)) {
470 dep |= (SSD_light | SSD_material);
472 if ((inp == SMO_clipplane_x) ||
473 (inp == SMO_apiview_clipplane_i)) {
474 dep |= SSD_clip_planes;
476 if (inp == SMO_texmat_i || inp == SMO_inv_texmat_i || inp == SMO_texscale_i) {
477 dep |= SSD_tex_matrix;
479 if ((inp == SMO_window_size) ||
480 (inp == SMO_pixel_size) ||
481 (inp == SMO_frame_number) ||
482 (inp == SMO_frame_time) ||
483 (inp == SMO_frame_delta)) {
486 if ((inp == SMO_clip_to_view) ||
487 (inp == SMO_view_to_clip) ||
488 (inp == SMO_apiclip_to_view) ||
489 (inp == SMO_view_to_apiclip) ||
490 (inp == SMO_apiview_to_apiclip) ||
491 (inp == SMO_apiclip_to_apiview)) {
492 dep |= SSD_projection;
494 if (inp == SMO_tex_is_alpha_i || inp == SMO_texcolor_i) {
495 dep |= SSD_texture | SSD_frame;
512 if (spec._func == SMF_first) {
513 spec._part[1] = SMO_INVALID;
514 spec._arg[1] =
nullptr;
516 if (spec._func == SMF_compose) {
517 if (spec._part[1] == SMO_identity) {
518 spec._func = SMF_first;
521 if (spec._func == SMF_compose) {
522 if (spec._part[0] == SMO_identity) {
523 spec._func = SMF_first;
524 spec._part[0] = spec._part[1];
525 spec._arg[0] = spec._arg[1];
530 if (spec._part[0] == SMO_model_to_view &&
531 spec._part[1] == SMO_view_to_apiclip) {
532 spec._part[0] = SMO_model_to_apiview;
533 spec._part[1] = SMO_apiview_to_apiclip;
535 }
else if (spec._part[0] == SMO_apiclip_to_view &&
536 spec._part[1] == SMO_view_to_model) {
537 spec._part[0] = SMO_apiclip_to_apiview;
538 spec._part[1] = SMO_apiview_to_model;
540 }
else if (spec._part[0] == SMO_apiview_to_view &&
541 spec._part[1] == SMO_view_to_apiclip) {
542 spec._func = SMF_first;
543 spec._part[0] = SMO_apiview_to_apiclip;
544 spec._part[1] = SMO_identity;
546 }
else if (spec._part[0] == SMO_apiclip_to_view &&
547 spec._part[1] == SMO_view_to_apiview) {
548 spec._func = SMF_first;
549 spec._part[0] = SMO_apiclip_to_apiview;
550 spec._part[1] = SMO_identity;
552 }
else if (spec._part[0] == SMO_apiview_to_view &&
553 spec._part[1] == SMO_view_to_model) {
554 spec._func = SMF_first;
555 spec._part[0] = SMO_apiview_to_model;
556 spec._part[1] = SMO_identity;
558 }
else if (spec._part[0] == SMO_model_to_view &&
559 spec._part[1] == SMO_view_to_apiview) {
560 spec._func = SMF_first;
561 spec._part[0] = SMO_model_to_apiview;
562 spec._part[1] = SMO_identity;
577 cg_recurse_parameters(CGparameter parameter,
const ShaderType &type,
580 if (parameter == 0) {
585 if (cgIsParameterReferenced(parameter)) {
586 int arg_dim[] = {1,0,0};
587 ShaderArgDir arg_dir = cg_parameter_dir(parameter);
588 ShaderArgType arg_type = cg_parameter_type(parameter);
589 ShaderArgClass arg_class = cg_parameter_class(parameter);
590 ShaderArgClass arg_subclass = arg_class;
592 CGenum vbl = cgGetParameterVariability(parameter);
593 CGtype base_type = cgGetParameterBaseType(parameter);
595 if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
596 switch (cgGetParameterType(parameter)) {
598 cg_recurse_parameters(
599 cgGetFirstStructParameter(parameter), type, success);
603 arg_type = cg_parameter_type(cgGetArrayParameter(parameter, 0));
604 arg_subclass = cg_parameter_class(cgGetArrayParameter(parameter, 0));
606 arg_dim[0] = cgGetArraySize(parameter, 0);
610 arg_dim[1] = cgGetParameterRows(parameter);
611 arg_dim[2] = cgGetParameterColumns(parameter);
614 p._id._name = cgGetParameterName(parameter);
617 p._class = arg_class;
618 p._subclass = arg_subclass;
620 p._direction = arg_dir;
621 p._varying = (vbl == CG_VARYING);
622 p._cat = shader_cat.get_safe_ptr();
632 p._numeric_type = SPT_uint;
638 p._numeric_type = SPT_int;
641 p._numeric_type = SPT_float;
650 }
else if (shader_cat.is_debug()) {
652 <<
"Parameter " << cgGetParameterName(parameter)
653 <<
" is unreferenced within shader " <<
get_filename(type) <<
"\n";
655 }
while((parameter = cgGetNextParameter(parameter))!= 0);
669 if (p._id._name.size() == 0)
return true;
670 if (p._id._name[0] ==
'$')
return true;
673 size_t loc = p._id._name.find_last_of(
'.');
675 string basename (p._id._name);
676 string struct_name (
"");
678 if (loc < string::npos) {
679 basename = p._id._name.substr(loc + 1);
680 struct_name = p._id._name.substr(0,loc+1);
684 vector_string pieces;
687 if (basename.size() >= 2 && basename.substr(0, 2) ==
"__") {
692 if (pieces[0] ==
"vtx") {
700 bind._append_uv = -1;
701 bind._numeric_type = p._numeric_type;
703 if (pieces.size() == 2) {
704 if (pieces[1] ==
"position") {
705 bind._name = InternalName::get_vertex();
706 bind._append_uv = -1;
707 _var_spec.push_back(bind);
710 if (pieces[1].substr(0, 8) ==
"texcoord") {
711 bind._name = InternalName::get_texcoord();
712 if (pieces[1].size() > 8) {
713 bind._append_uv = atoi(pieces[1].c_str() + 8);
715 _var_spec.push_back(bind);
718 if (pieces[1].substr(0, 7) ==
"tangent") {
719 bind._name = InternalName::get_tangent();
720 if (pieces[1].size() > 7) {
721 bind._append_uv = atoi(pieces[1].c_str() + 7);
723 _var_spec.push_back(bind);
726 if (pieces[1].substr(0, 8) ==
"binormal") {
727 bind._name = InternalName::get_binormal();
728 if (pieces[1].size() > 8) {
729 bind._append_uv = atoi(pieces[1].c_str() + 8);
731 _var_spec.push_back(bind);
734 }
else if (pieces.size() == 3) {
735 if (pieces[1] ==
"transform") {
736 if (pieces[2] ==
"blend") {
737 bind._name = InternalName::get_transform_blend();
738 _var_spec.push_back(bind);
741 if (pieces[2] ==
"index") {
742 bind._name = InternalName::get_transform_index();
743 _var_spec.push_back(bind);
746 if (pieces[2] ==
"weight") {
747 bind._name = InternalName::get_transform_weight();
748 _var_spec.push_back(bind);
754 bind._name = InternalName::get_root();
755 for (
size_t i = 1; i < pieces.size(); ++i) {
756 bind._name = bind._name->append(pieces[i]);
758 _var_spec.push_back(bind);
762 if (pieces[0] ==
"mat" && pieces[1] ==
"shadow") {
771 bind._piece = SMP_whole;
772 bind._func = SMF_compose;
773 bind._part[1] = SMO_light_source_i_attrib;
774 bind._arg[1] = InternalName::make(
"shadowViewMatrix");
775 bind._part[0] = SMO_view_to_apiview;
776 bind._arg[0] =
nullptr;
777 bind._index = atoi(pieces[2].c_str());
780 _mat_spec.push_back(bind);
781 _mat_deps |= bind._dep[0] | bind._dep[1];
788 if (pieces[0] ==
"mstrans") {
790 pieces.push_back(
"to");
791 pieces.push_back(
"model");
793 if (pieces[0] ==
"wstrans") {
795 pieces.push_back(
"to");
796 pieces.push_back(
"world");
798 if (pieces[0] ==
"vstrans") {
800 pieces.push_back(
"to");
801 pieces.push_back(
"view");
803 if (pieces[0] ==
"cstrans") {
805 pieces.push_back(
"to");
806 pieces.push_back(
"clip");
808 if (pieces[0] ==
"mspos") {
810 pieces.push_back(
"to");
811 pieces.push_back(
"model");
813 if (pieces[0] ==
"wspos") {
815 pieces.push_back(
"to");
816 pieces.push_back(
"world");
818 if (pieces[0] ==
"vspos") {
820 pieces.push_back(
"to");
821 pieces.push_back(
"view");
823 if (pieces[0] ==
"cspos") {
825 pieces.push_back(
"to");
826 pieces.push_back(
"clip");
831 if ((pieces[0] ==
"mat")||(pieces[0] ==
"inv")||
832 (pieces[0] ==
"tps")||(pieces[0] ==
"itp")) {
836 string trans = pieces[0];
837 string matrix = pieces[1];
839 if (matrix ==
"modelview") {
840 tokenize(
"trans_model_to_apiview", pieces,
"_");
841 }
else if (matrix ==
"projection") {
842 tokenize(
"trans_apiview_to_apiclip", pieces,
"_");
843 }
else if (matrix ==
"modelproj") {
844 tokenize(
"trans_model_to_apiclip", pieces,
"_");
851 }
else if (trans==
"inv") {
852 string t = pieces[1];
853 pieces[1] = pieces[3];
855 }
else if (trans==
"tps") {
857 }
else if (trans==
"itp") {
858 string t = pieces[1];
859 pieces[1] = pieces[3];
867 if ((pieces[0]==
"trans")||
868 (pieces[0]==
"tpose")||
869 (pieces[0]==
"row0")||
870 (pieces[0]==
"row1")||
871 (pieces[0]==
"row2")||
872 (pieces[0]==
"row3")||
873 (pieces[0]==
"col0")||
874 (pieces[0]==
"col1")||
875 (pieces[0]==
"col2")||
876 (pieces[0]==
"col3")) {
884 bind._piece = SMP_whole;
885 bind._func = SMF_compose;
886 bind._part[1] = SMO_light_source_i_attrib;
887 bind._arg[1] = InternalName::make(
"shadowViewMatrix");
888 bind._part[0] = SMO_view_to_apiview;
889 bind._arg[0] =
nullptr;
890 bind._index = atoi(pieces[2].c_str());
893 pieces.push_back(
"");
896 if (pieces[0]==
"trans") bind._piece = SMP_whole;
897 else if (pieces[0]==
"tpose") bind._piece = SMP_transpose;
898 else if (pieces[0]==
"row0") bind._piece = SMP_row0;
899 else if (pieces[0]==
"row1") bind._piece = SMP_row1;
900 else if (pieces[0]==
"row2") bind._piece = SMP_row2;
901 else if (pieces[0]==
"row3") bind._piece = SMP_row3;
902 else if (pieces[0]==
"col0") bind._piece = SMP_col0;
903 else if (pieces[0]==
"col1") bind._piece = SMP_col1;
904 else if (pieces[0]==
"col2") bind._piece = SMP_col2;
905 else if (pieces[0]==
"col3") bind._piece = SMP_col3;
906 if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
907 if (p._type == SAT_mat3x3) {
910 if (bind._piece == SMP_transpose) {
911 bind._piece = SMP_transpose3x3;
913 bind._piece = SMP_upper3x3;
935 _mat_spec.push_back(bind);
936 _mat_deps |= bind._dep[0] | bind._dep[1];
942 if (pieces[0] ==
"attr") {
949 if (pieces[1] ==
"material") {
954 bind._piece = SMP_transpose;
955 bind._func = SMF_first;
956 bind._part[0] = SMO_attr_material;
957 bind._arg[0] =
nullptr;
958 bind._part[1] = SMO_identity;
959 bind._arg[1] =
nullptr;
960 }
else if (pieces[1] ==
"color") {
965 bind._piece = SMP_row3;
966 bind._func = SMF_first;
967 bind._part[0] = SMO_attr_color;
968 bind._arg[0] =
nullptr;
969 bind._part[1] = SMO_identity;
970 bind._arg[1] =
nullptr;
971 }
else if (pieces[1] ==
"colorscale") {
976 bind._piece = SMP_row3;
977 bind._func = SMF_first;
978 bind._part[0] = SMO_attr_colorscale;
979 bind._arg[0] =
nullptr;
980 bind._part[1] = SMO_identity;
981 bind._arg[1] =
nullptr;
982 }
else if (pieces[1] ==
"fog") {
987 bind._piece = SMP_row3;
988 bind._func = SMF_first;
989 bind._part[0] = SMO_attr_fog;
990 bind._arg[0] =
nullptr;
991 bind._part[1] = SMO_identity;
992 bind._arg[1] =
nullptr;
993 }
else if (pieces[1] ==
"fogcolor") {
998 bind._piece = SMP_row3;
999 bind._func = SMF_first;
1000 bind._part[0] = SMO_attr_fogcolor;
1001 bind._arg[0] =
nullptr;
1002 bind._part[1] = SMO_identity;
1003 bind._arg[1] =
nullptr;
1004 }
else if (pieces[1] ==
"ambient") {
1009 bind._piece = SMP_row3;
1010 bind._func = SMF_first;
1011 bind._part[0] = SMO_light_ambient;
1012 bind._arg[0] =
nullptr;
1013 bind._part[1] = SMO_identity;
1014 bind._arg[1] =
nullptr;
1015 }
else if (pieces[1].compare(0, 5,
"light") == 0) {
1020 bind._piece = SMP_transpose;
1021 bind._func = SMF_first;
1022 bind._part[0] = SMO_light_source_i_packed;
1023 bind._arg[0] =
nullptr;
1024 bind._part[1] = SMO_identity;
1025 bind._arg[1] =
nullptr;
1026 bind._index = atoi(pieces[1].c_str() + 5);
1027 }
else if (pieces[1].compare(0, 5,
"lspec") == 0) {
1032 bind._piece = SMP_row3;
1033 bind._func = SMF_first;
1034 bind._part[0] = SMO_light_source_i_attrib;
1035 bind._arg[0] = InternalName::make(
"specular");
1036 bind._part[1] = SMO_identity;
1037 bind._arg[1] =
nullptr;
1038 bind._index = atoi(pieces[1].c_str() + 5);
1045 _mat_spec.push_back(bind);
1046 _mat_deps |= bind._dep[0] | bind._dep[1];
1050 if (pieces[0] ==
"color") {
1059 _mat_spec.push_back(bind);
1060 _mat_deps |= bind._dep[0] | bind._dep[1];
1066 if (pieces[0] ==
"alight") {
1075 bind._piece = SMP_row3;
1076 bind._func = SMF_first;
1077 bind._part[0] = SMO_alight_x;
1078 bind._arg[0] = InternalName::make(pieces[1]);
1079 bind._part[1] = SMO_identity;
1080 bind._arg[1] =
nullptr;
1083 _mat_spec.push_back(bind);
1084 _mat_deps |= bind._dep[0] | bind._dep[1];
1088 if (pieces[0] ==
"satten") {
1097 bind._piece = SMP_row3;
1098 bind._func = SMF_first;
1099 bind._part[0] = SMO_satten_x;
1100 bind._arg[0] = InternalName::make(pieces[1]);
1101 bind._part[1] = SMO_identity;
1102 bind._arg[1] =
nullptr;
1105 _mat_spec.push_back(bind);
1106 _mat_deps |= bind._dep[0] | bind._dep[1];
1110 if ((pieces[0]==
"dlight")||(pieces[0]==
"plight")||(pieces[0]==
"slight")) {
1118 bind._piece = SMP_transpose;
1120 pieces.push_back(
"");
1121 if (pieces[next] ==
"") {
1125 if (pieces[0] ==
"dlight") {
1126 bind._func = SMF_transform_dlight;
1127 bind._part[0] = SMO_dlight_x;
1128 }
else if (pieces[0] ==
"plight") {
1129 bind._func = SMF_transform_plight;
1130 bind._part[0] = SMO_plight_x;
1131 }
else if (pieces[0] ==
"slight") {
1132 bind._func = SMF_transform_slight;
1133 bind._part[0] = SMO_slight_x;
1135 bind._arg[0] = InternalName::make(pieces[next]);
1147 _mat_spec.push_back(bind);
1148 _mat_deps |= bind._dep[0] | bind._dep[1];
1152 if (pieces[0] ==
"texmat") {
1161 bind._piece = SMP_whole;
1162 bind._func = SMF_first;
1163 bind._part[0] = SMO_texmat_i;
1164 bind._arg[0] =
nullptr;
1165 bind._part[1] = SMO_identity;
1166 bind._arg[1] =
nullptr;
1167 bind._index = atoi(pieces[1].c_str());
1170 _mat_spec.push_back(bind);
1171 _mat_deps |= bind._dep[0] | bind._dep[1];
1175 if (pieces[0] ==
"texscale") {
1184 bind._piece = SMP_row3;
1185 bind._func = SMF_first;
1186 bind._part[0] = SMO_texscale_i;
1187 bind._arg[0] =
nullptr;
1188 bind._part[1] = SMO_identity;
1189 bind._arg[1] =
nullptr;
1190 bind._index = atoi(pieces[1].c_str());
1193 _mat_spec.push_back(bind);
1194 _mat_deps |= bind._dep[0] | bind._dep[1];
1198 if (pieces[0] ==
"texcolor") {
1207 bind._piece = SMP_row3;
1208 bind._func = SMF_first;
1209 bind._part[0] = SMO_texcolor_i;
1210 bind._arg[0] =
nullptr;
1211 bind._part[1] = SMO_identity;
1212 bind._arg[1] =
nullptr;
1213 bind._index = atoi(pieces[1].c_str());
1216 _mat_spec.push_back(bind);
1217 _mat_deps |= bind._dep[0] | bind._dep[1];
1221 if (pieces[0] ==
"plane") {
1230 bind._piece = SMP_row3;
1231 bind._func = SMF_first;
1232 bind._part[0] = SMO_plane_x;
1233 bind._arg[0] = InternalName::make(pieces[1]);
1234 bind._part[1] = SMO_identity;
1235 bind._arg[1] =
nullptr;
1238 _mat_spec.push_back(bind);
1239 _mat_deps |= bind._dep[0] | bind._dep[1];
1243 if (pieces[0] ==
"clipplane") {
1252 bind._piece = SMP_row3;
1253 bind._func = SMF_first;
1254 bind._part[0] = SMO_clipplane_x;
1255 bind._arg[0] = InternalName::make(pieces[1]);
1256 bind._part[1] = SMO_identity;
1257 bind._arg[1] =
nullptr;
1260 _mat_spec.push_back(bind);
1261 _mat_deps |= bind._dep[0] | bind._dep[1];
1267 if (pieces[0] ==
"sys") {
1275 bind._piece = SMP_row3;
1276 bind._func = SMF_first;
1277 bind._part[1] = SMO_identity;
1278 bind._arg[1] =
nullptr;
1279 if (pieces[1] ==
"pixelsize") {
1283 bind._part[0] = SMO_pixel_size;
1284 bind._arg[0] =
nullptr;
1286 }
else if (pieces[1] ==
"windowsize") {
1290 bind._part[0] = SMO_window_size;
1291 bind._arg[0] =
nullptr;
1293 }
else if (pieces[1] ==
"time") {
1297 bind._piece = SMP_row3x1;
1298 bind._part[0] = SMO_frame_time;
1299 bind._arg[0] =
nullptr;
1307 _mat_spec.push_back(bind);
1308 _mat_deps |= bind._dep[0] | bind._dep[1];
1314 if (pieces[0] ==
"tex") {
1319 if ((pieces.size() != 2)&&(pieces.size() != 3)) {
1325 bind._name =
nullptr;
1326 bind._stage = atoi(pieces[1].c_str());
1327 bind._part = STO_stage_i;
1329 case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture;
break;
1330 case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture;
break;
1331 case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture;
break;
1332 case SAT_sampler2d_array:bind._desired_type = Texture::TT_2d_texture_array;
break;
1333 case SAT_sampler_cube: bind._desired_type = Texture::TT_cube_map;
break;
1334 case SAT_sampler_buffer: bind._desired_type = Texture::TT_buffer_texture;
break;
1335 case SAT_sampler_cube_array:bind._desired_type = Texture::TT_cube_map_array;
break;
1340 if (pieces.size() == 3) {
1341 bind._suffix = InternalName::make(((
string)
"-") + pieces[2]);
1342 shader_cat.warning()
1343 <<
"Parameter " << p._id._name <<
": use of a texture suffix is deprecated.\n";
1345 _tex_spec.push_back(bind);
1349 if (pieces[0] ==
"shadow") {
1354 if (pieces.size() != 2) {
1360 bind._name =
nullptr;
1361 bind._stage = atoi(pieces[1].c_str());
1362 bind._part = STO_light_i_shadow_map;
1364 case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture;
break;
1365 case SAT_sampler_cube: bind._desired_type = Texture::TT_cube_map;
break;
1370 _tex_spec.push_back(bind);
1376 if (pieces[0] ==
"texpad") {
1385 bind._piece = SMP_row3;
1386 bind._func = SMF_first;
1387 bind._part[0] = SMO_texpad_x;
1388 bind._arg[0] = InternalName::make(pieces[1]);
1389 bind._part[1] = SMO_identity;
1390 bind._arg[1] =
nullptr;
1392 _mat_spec.push_back(bind);
1393 _mat_deps |= bind._dep[0] | bind._dep[1];
1397 if (pieces[0] ==
"texpix") {
1406 bind._piece = SMP_row3;
1407 bind._func = SMF_first;
1408 bind._part[0] = SMO_texpix_x;
1409 bind._arg[0] = InternalName::make(pieces[1]);
1410 bind._part[1] = SMO_identity;
1411 bind._arg[1] =
nullptr;
1413 _mat_spec.push_back(bind);
1414 _mat_deps |= bind._dep[0] | bind._dep[1];
1418 if (pieces[0] ==
"tbl") {
1423 if (pieces[0] ==
"l") {
1428 if (pieces[0] ==
"o") {
1439 bool k_prefix =
false;
1442 if (pieces[0] ==
"k") {
1444 basename = basename.substr(2);
1447 PT(
InternalName) kinputname = InternalName::make(struct_name + basename);
1454 if (!cp_errchk_parameter_ptr(p))
1459 bind._arg = kinputname;
1465 bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
1466 bind._dep[1] = SSD_NONE;
1468 memcpy(bind._dim,arg_dim,
sizeof(
int)*3);
1471 if (k_prefix) bind._dim[0] = -1;
1472 _ptr_spec.push_back(bind);
1478 case SAT_sampler1d: {
1481 bind._name = kinputname;
1482 bind._part = STO_named_input;
1483 bind._desired_type = Texture::TT_1d_texture;
1484 _tex_spec.push_back(bind);
1487 case SAT_sampler2d: {
1490 bind._name = kinputname;
1491 bind._part = STO_named_input;
1492 bind._desired_type = Texture::TT_2d_texture;
1493 _tex_spec.push_back(bind);
1496 case SAT_sampler3d: {
1499 bind._name = kinputname;
1500 bind._part = STO_named_input;
1501 bind._desired_type = Texture::TT_3d_texture;
1502 _tex_spec.push_back(bind);
1505 case SAT_sampler2d_array: {
1508 bind._name = kinputname;
1509 bind._part = STO_named_input;
1510 bind._desired_type = Texture::TT_2d_texture_array;
1511 _tex_spec.push_back(bind);
1514 case SAT_sampler_cube: {
1517 bind._name = kinputname;
1518 bind._part = STO_named_input;
1519 bind._desired_type = Texture::TT_cube_map;
1520 _tex_spec.push_back(bind);
1523 case SAT_sampler_buffer: {
1526 bind._name = kinputname;
1527 bind._part = STO_named_input;
1528 bind._desired_type = Texture::TT_buffer_texture;
1529 _tex_spec.push_back(bind);
1532 case SAT_sampler_cube_array: {
1535 bind._name = kinputname;
1536 bind._part = STO_named_input;
1537 bind._desired_type = Texture::TT_cube_map_array;
1538 _tex_spec.push_back(bind);
1559 clear_parameters() {
1569 set_compiled(
unsigned int format,
const char *data,
size_t length) {
1570 _compiled_format = format;
1571 _compiled_binary.assign(data, length);
1574 if (_cache_compiled_shader && !_record.is_null()) {
1575 _record->set_data(
this);
1578 cache->
store(_record);
1586 get_compiled(
unsigned int &format,
string &binary)
const {
1587 format = _compiled_format;
1588 binary = _compiled_binary;
1589 return !binary.empty();
1598 _default_caps = caps;
1605 Shader::ShaderArgType Shader::
1606 cg_parameter_type(CGparameter p) {
1607 switch (cgGetParameterClass(p)) {
1608 case CG_PARAMETERCLASS_SCALAR:
return SAT_scalar;
1609 case CG_PARAMETERCLASS_VECTOR:
1610 switch (cgGetParameterColumns(p)) {
1611 case 1:
return SAT_vec1;
1612 case 2:
return SAT_vec2;
1613 case 3:
return SAT_vec3;
1614 case 4:
return SAT_vec4;
1615 default:
return SAT_unknown;
1617 case CG_PARAMETERCLASS_MATRIX:
1618 switch (cgGetParameterRows(p)) {
1620 switch (cgGetParameterColumns(p)) {
1621 case 1:
return SAT_mat1x1;
1622 case 2:
return SAT_mat1x2;
1623 case 3:
return SAT_mat1x3;
1624 case 4:
return SAT_mat1x4;
1625 default:
return SAT_unknown;
1628 switch (cgGetParameterColumns(p)) {
1629 case 1:
return SAT_mat2x1;
1630 case 2:
return SAT_mat2x2;
1631 case 3:
return SAT_mat2x3;
1632 case 4:
return SAT_mat2x4;
1633 default:
return SAT_unknown;
1636 switch (cgGetParameterColumns(p)) {
1637 case 1:
return SAT_mat3x1;
1638 case 2:
return SAT_mat3x2;
1639 case 3:
return SAT_mat3x3;
1640 case 4:
return SAT_mat3x4;
1641 default:
return SAT_unknown;
1644 switch (cgGetParameterColumns(p)) {
1645 case 1:
return SAT_mat4x1;
1646 case 2:
return SAT_mat4x2;
1647 case 3:
return SAT_mat4x3;
1648 case 4:
return SAT_mat4x4;
1649 default:
return SAT_unknown;
1651 default:
return SAT_unknown;
1653 case CG_PARAMETERCLASS_SAMPLER:
1654 switch (cgGetParameterType(p)) {
1655 case CG_SAMPLER1D:
return Shader::SAT_sampler1d;
1656 case CG_SAMPLER2D:
return Shader::SAT_sampler2d;
1657 case CG_SAMPLER3D:
return Shader::SAT_sampler3d;
1658 case CG_SAMPLER2DARRAY:
return Shader::SAT_sampler2d_array;
1659 case CG_SAMPLERCUBE:
return Shader::SAT_sampler_cube;
1660 case CG_SAMPLERBUF:
return Shader::SAT_sampler_buffer;
1661 case CG_SAMPLERCUBEARRAY:
return Shader::SAT_sampler_cube_array;
1663 case 1313:
return Shader::SAT_sampler1d;
1664 case 1314:
return Shader::SAT_sampler2d;
1665 default:
return SAT_unknown;
1667 case CG_PARAMETERCLASS_ARRAY:
return SAT_unknown;
1676 Shader::ShaderArgClass Shader::cg_parameter_class(CGparameter p) {
1677 switch (cgGetParameterClass(p)) {
1678 case CG_PARAMETERCLASS_SCALAR:
return Shader::SAC_scalar;
1679 case CG_PARAMETERCLASS_VECTOR:
return Shader::SAC_vector;
1680 case CG_PARAMETERCLASS_MATRIX:
return Shader::SAC_matrix;
1681 case CG_PARAMETERCLASS_SAMPLER:
return Shader::SAC_sampler;
1682 case CG_PARAMETERCLASS_ARRAY:
return Shader::SAC_array;
1683 default:
return Shader::SAC_unknown;
1690 Shader::ShaderArgDir Shader::
1691 cg_parameter_dir(CGparameter p) {
1692 switch (cgGetParameterDirection(p)) {
1693 case CG_IN:
return Shader::SAD_in;
1694 case CG_OUT:
return Shader::SAD_out;
1695 case CG_INOUT:
return Shader::SAD_inout;
1696 default:
return Shader::SAD_unknown;
1704 cg_release_resources() {
1705 if (_cg_vprogram != 0) {
1706 cgDestroyProgram(_cg_vprogram);
1709 if (_cg_fprogram != 0) {
1710 cgDestroyProgram(_cg_fprogram);
1713 if (_cg_gprogram != 0) {
1714 cgDestroyProgram(_cg_gprogram);
1723 cg_compile_entry_point(
const char *entry,
const ShaderCaps &caps,
1724 CGcontext context, ShaderType type) {
1727 const char *compiler_args[100];
1728 const string text =
get_text(type);
1731 int active, ultimate;
1735 active = caps._active_vprofile;
1736 ultimate = caps._ultimate_vprofile;
1740 active = caps._active_fprofile;
1741 ultimate = caps._ultimate_fprofile;
1745 active = caps._active_gprofile;
1746 ultimate = caps._ultimate_gprofile;
1749 case ST_tess_evaluation:
1750 case ST_tess_control:
1751 active = caps._active_tprofile;
1752 ultimate = caps._ultimate_tprofile;
1757 active = CG_PROFILE_UNKNOWN;
1758 ultimate = CG_PROFILE_UNKNOWN;
1761 if (type == ST_fragment && caps._bug_list.count(SBUG_ati_draw_buffers)) {
1762 compiler_args[nargs++] =
"-po";
1763 compiler_args[nargs++] =
"ATI_draw_buffers";
1767 if (!cg_glsl_version.empty() && active != CG_PROFILE_UNKNOWN &&
1768 cgGetProfileProperty((CGprofile) active, CG_IS_GLSL_PROFILE)) {
1770 version_arg =
"version=";
1771 version_arg += cg_glsl_version;
1773 compiler_args[nargs++] =
"-po";
1774 compiler_args[nargs++] = version_arg.c_str();
1777 compiler_args[nargs] = 0;
1781 if ((active != (
int)CG_PROFILE_UNKNOWN) && (active != ultimate)) {
1783 if (shader_cat.is_debug()) {
1785 <<
"Compiling Cg shader " <<
get_filename(type) <<
" with entry point " << entry
1786 <<
" and active profile " << cgGetProfileString((CGprofile) active) <<
"\n";
1789 shader_cat.debug() <<
"Using compiler arguments:";
1790 for (
int i = 0; i < nargs; ++i) {
1791 shader_cat.debug(
false) <<
" " << compiler_args[i];
1793 shader_cat.debug(
false) <<
"\n";
1798 prog = cgCreateProgram(context, CG_SOURCE, text.c_str(),
1799 (CGprofile)active, entry, (
const char **)compiler_args);
1801 if (err == CG_NO_ERROR) {
1805 cgDestroyProgram(prog);
1807 if (shader_cat.is_debug()) {
1809 <<
"Compilation with active profile failed: " << cgGetErrorString(err) <<
"\n";
1810 if (err == CG_COMPILER_ERROR) {
1811 const char *listing = cgGetLastListing(context);
1812 if (listing !=
nullptr) {
1813 shader_cat.debug(
false) << listing;
1819 if (shader_cat.is_debug()) {
1821 <<
"Compiling Cg shader " <<
get_filename(type) <<
" with entry point " << entry
1822 <<
" and ultimate profile " << cgGetProfileString((CGprofile) ultimate) <<
"\n";
1826 prog = cgCreateProgram(context, CG_SOURCE, text.c_str(),
1827 (CGprofile)ultimate, entry,
nullptr);
1831 const char *listing = cgGetLastListing(context);
1833 if (err == CG_NO_ERROR && listing !=
nullptr && strlen(listing) > 1) {
1834 shader_cat.warning()
1835 <<
"Encountered warnings during compilation of " <<
get_filename(type)
1836 <<
":\n" << listing;
1838 }
else if (err == CG_COMPILER_ERROR) {
1840 <<
"Failed to compile Cg shader " <<
get_filename(type);
1841 if (listing !=
nullptr) {
1842 shader_cat.error(
false) <<
":\n" << listing;
1844 shader_cat.error(
false) <<
"!\n";
1848 if (err == CG_NO_ERROR) {
1852 if (shader_cat.is_debug()) {
1854 <<
"Compilation with ultimate profile failed: " << cgGetErrorString(err) <<
"\n";
1858 cgDestroyProgram(prog);
1869 cg_compile_shader(
const ShaderCaps &caps, CGcontext context) {
1870 _cg_last_caps = caps;
1872 if (!_text._separate || !_text._vertex.empty()) {
1873 _cg_vprogram = cg_compile_entry_point(
"vshader", caps, context, ST_vertex);
1874 if (_cg_vprogram == 0) {
1875 cg_release_resources();
1878 _cg_vprofile = cgGetProgramProfile(_cg_vprogram);
1881 if (!_text._separate || !_text._fragment.empty()) {
1882 _cg_fprogram = cg_compile_entry_point(
"fshader", caps, context, ST_fragment);
1883 if (_cg_fprogram == 0) {
1884 cg_release_resources();
1887 _cg_fprofile = cgGetProgramProfile(_cg_fprogram);
1890 if ((_text._separate && !_text._geometry.empty()) || (!_text._separate && _text._shared.find(
"gshader") != string::npos)) {
1891 _cg_gprogram = cg_compile_entry_point(
"gshader", caps, context, ST_geometry);
1892 if (_cg_gprogram == 0) {
1893 cg_release_resources();
1896 _cg_gprofile = cgGetProgramProfile(_cg_gprogram);
1899 if (_cg_vprogram == 0 && _cg_fprogram == 0 && _cg_gprogram == 0) {
1900 shader_cat.error() <<
"Shader must at least have one program!\n";
1901 cg_release_resources();
1909 if (_cg_fprofile == CG_PROFILE_PS_2_0 ||
1910 _cg_fprofile == CG_PROFILE_PS_2_X ||
1911 _cg_fprofile == CG_PROFILE_PS_3_0) {
1912 vector_string lines;
1913 tokenize(cgGetProgramString(_cg_fprogram, CG_COMPILED_PROGRAM), lines,
"\n");
1916 int num_modified = 0;
1918 for (
size_t i = 0; i < lines.size(); ++i) {
1919 const string &line = lines[i];
1921 size_t space = line.find(
' ');
1922 if (space == string::npos) {
1923 out << line <<
'\n';
1927 string instr = line.substr(0, space);
1930 if (instr.compare(0, 5,
"texld") == 0 &&
1931 instr.compare(instr.size() - 4, 4,
"_sat") == 0) {
1933 string reg = line.substr(space + 1, line.find(
',', space) - space - 1);
1936 instr.resize(instr.size() - 4);
1937 out << instr <<
' ' << line.substr(space + 1) <<
'\n';
1938 out <<
"mov_sat " << reg <<
", " << reg <<
'\n';
1941 out << line <<
'\n';
1945 if (num_modified > 0) {
1946 string result = out.str();
1947 CGprogram new_program;
1948 new_program = cgCreateProgram(context, CG_OBJECT, result.c_str(),
1949 (CGprofile)_cg_fprofile,
"fshader",
1952 cgDestroyProgram(_cg_fprogram);
1953 _cg_fprogram = new_program;
1955 if (shader_cat.is_debug()) {
1957 <<
"Replaced " << num_modified <<
" invalid texld_sat instruction"
1958 << ((num_modified == 1) ?
"" :
"s") <<
" in compiled shader\n";
1961 shader_cat.warning()
1962 <<
"Failed to load shader with fixed texld_sat instructions: "
1963 << cgGetErrorString(cgGetError()) <<
"\n";
1969 if (shader_cat.is_debug()) {
1970 const char *vertex_program;
1971 const char *fragment_program;
1972 const char *geometry_program;
1974 if (_cg_vprogram != 0) {
1976 <<
"Cg vertex profile: " << cgGetProfileString((CGprofile)_cg_vprofile) <<
"\n";
1977 vertex_program = cgGetProgramString(_cg_vprogram, CG_COMPILED_PROGRAM);
1978 shader_cat.spam() << vertex_program <<
"\n";
1980 if (_cg_fprogram != 0) {
1982 <<
"Cg fragment profile: " << cgGetProfileString((CGprofile)_cg_fprofile) <<
"\n";
1983 fragment_program = cgGetProgramString(_cg_fprogram, CG_COMPILED_PROGRAM);
1984 shader_cat.spam() << fragment_program <<
"\n";
1986 if (_cg_gprogram != 0) {
1988 <<
"Cg geometry profile: " << cgGetProfileString((CGprofile)_cg_gprofile) <<
"\n";
1989 geometry_program = cgGetProgramString(_cg_gprogram, CG_COMPILED_PROGRAM);
1990 shader_cat.spam() << geometry_program <<
"\n";
2001 cg_analyze_entry_point(CGprogram prog, ShaderType type) {
2002 bool success =
true;
2004 cg_recurse_parameters(cgGetFirstParameter(prog, CG_PROGRAM), type, success);
2033 cg_analyze_shader(
const ShaderCaps &caps) {
2036 if (_cg_context == 0) {
2037 _cg_context = cgCreateContext();
2038 if (_cg_context == 0) {
2040 <<
"Could not create a Cg context object: "
2041 << cgGetErrorString(cgGetError()) <<
"\n";
2046 if (!cg_compile_shader(caps, _cg_context)) {
2050 if (_cg_fprogram != 0) {
2051 if (!cg_analyze_entry_point(_cg_fprogram, ST_fragment)) {
2052 cg_release_resources();
2058 if (_var_spec.size() != 0) {
2059 shader_cat.error() <<
"Cannot use vtx parameters in an fshader\n";
2060 cg_release_resources();
2065 if (_cg_vprogram != 0) {
2066 if (!cg_analyze_entry_point(_cg_vprogram, ST_vertex)) {
2067 cg_release_resources();
2073 if (_cg_gprogram != 0) {
2074 if (!cg_analyze_entry_point(_cg_gprogram, ST_geometry)) {
2075 cg_release_resources();
2084 for (
size_t i = 0; i < _var_spec.size(); ++i) {
2085 _var_spec[i]._id._seqno = seqno++;
2087 for (
size_t i = 0; i < _mat_spec.size(); ++i) {
2088 _mat_spec[i]._id._seqno = seqno++;
2090 for (
size_t i = 0; i < _tex_spec.size(); ++i) {
2091 _tex_spec[i]._id._seqno = seqno++;
2094 for (
size_t i = 0; i < _ptr_spec.size(); ++i) {
2095 _ptr_spec[i]._id._seqno = seqno++;
2096 _ptr_spec[i]._info._id = _ptr_spec[i]._id;
2174 cg_release_resources();
2182 cg_program_from_shadertype(ShaderType type) {
2185 return _cg_vprogram;
2188 return _cg_fprogram;
2191 return _cg_gprogram;
2204 cg_compile_for(
const ShaderCaps &caps, CGcontext context,
2208 combined_program = 0;
2214 _default_caps = caps;
2215 if (!cg_compile_shader(caps, context)) {
2221 if (_cg_vprogram != 0 && _cg_vprofile != caps._active_vprofile) {
2222 shader_cat.error() <<
"Cg vertex program not supported by profile "
2223 << cgGetProfileString((CGprofile) caps._active_vprofile) <<
": "
2224 <<
get_filename(ST_vertex) <<
". Try choosing a different profile.\n";
2227 if (_cg_fprogram != 0 && _cg_fprofile != caps._active_fprofile) {
2228 shader_cat.error() <<
"Cg fragment program not supported by profile "
2229 << cgGetProfileString((CGprofile) caps._active_fprofile) <<
": "
2230 <<
get_filename(ST_fragment) <<
". Try choosing a different profile.\n";
2233 if (_cg_gprogram != 0 && _cg_gprofile != caps._active_gprofile) {
2234 shader_cat.error() <<
"Cg geometry program not supported by profile "
2235 << cgGetProfileString((CGprofile) caps._active_gprofile) <<
": "
2236 <<
get_filename(ST_geometry) <<
". Try choosing a different profile.\n";
2242 if (_cg_vprogram != 0) {
2243 programs.push_back(_cg_vprogram);
2245 if (_cg_fprogram != 0) {
2246 programs.push_back(_cg_fprogram);
2248 if (_cg_gprogram != 0) {
2249 programs.push_back(_cg_gprogram);
2255 combined_program = cgCombinePrograms(programs.size(), &programs[0]);
2258 size_t n_mat = _mat_spec.size();
2259 size_t n_tex = _tex_spec.size();
2260 size_t n_var = _var_spec.size();
2261 size_t n_ptr = _ptr_spec.size();
2263 map.resize(n_mat + n_tex + n_var + n_ptr);
2267 CGprogram programs_by_type[ST_COUNT];
2268 for (
int i = 0; i < cgGetNumProgramDomains(combined_program); ++i) {
2270 CGprogram program = cgGetProgramDomainProgram(combined_program, i);
2271 programs_by_type[cgGetProgramDomain(program)] = program;
2274 for (
size_t i = 0; i < n_mat; ++i) {
2275 const ShaderArgId &
id = _mat_spec[i]._id;
2276 map[
id._seqno] = cgGetNamedParameter(programs_by_type[
id._type],
id._name.c_str());
2278 if (shader_cat.is_debug()) {
2279 const char *resource = cgGetParameterResourceName(map[
id._seqno]);
2280 if (resource !=
nullptr) {
2281 shader_cat.debug() <<
"Uniform parameter " <<
id._name
2282 <<
" is bound to resource " << resource <<
"\n";
2287 for (
size_t i = 0; i < n_tex; ++i) {
2288 const ShaderArgId &
id = _tex_spec[i]._id;
2289 CGparameter p = cgGetNamedParameter(programs_by_type[
id._type],
id._name.c_str());
2291 if (shader_cat.is_debug()) {
2292 const char *resource = cgGetParameterResourceName(p);
2293 if (resource !=
nullptr) {
2294 shader_cat.debug() <<
"Texture parameter " <<
id._name
2295 <<
" is bound to resource " << resource <<
"\n";
2301 for (
size_t i = 0; i < n_var; ++i) {
2302 const ShaderArgId &
id = _var_spec[i]._id;
2303 CGparameter p = cgGetNamedParameter(programs_by_type[
id._type],
id._name.c_str());
2305 const char *resource = cgGetParameterResourceName(p);
2306 if (shader_cat.is_debug() && resource !=
nullptr) {
2307 if (cgGetParameterResource(p) == CG_GLSL_ATTRIB) {
2309 <<
"Varying parameter " <<
id._name <<
" is bound to GLSL attribute "
2310 << resource <<
"\n";
2313 <<
"Varying parameter " <<
id._name <<
" is bound to resource "
2314 << resource <<
" (" << cgGetParameterResource(p)
2315 <<
", index " << cgGetParameterResourceIndex(p) <<
")\n";
2322 for (
size_t i = 0; i < n_ptr; ++i) {
2323 const ShaderArgId &
id = _ptr_spec[i]._id;
2324 map[
id._seqno] = cgGetNamedParameter(programs_by_type[
id._type],
id._name.c_str());
2326 if (shader_cat.is_debug()) {
2327 const char *resource = cgGetParameterResourceName(map[
id._seqno]);
2328 if (resource !=
nullptr) {
2329 shader_cat.debug() <<
"Uniform ptr parameter " <<
id._name
2330 <<
" is bound to resource " << resource <<
"\n";
2336 if (_cg_vprogram != 0) {
2337 cgDestroyProgram(_cg_vprogram);
2340 if (_cg_fprogram != 0) {
2341 cgDestroyProgram(_cg_fprogram);
2344 if (_cg_gprogram != 0) {
2345 cgDestroyProgram(_cg_gprogram);
2349 _cg_last_caps.clear();
2359 Shader(ShaderLanguage lang) :
2366 _cache_compiled_shader(false)
2372 _cg_vprofile = CG_PROFILE_UNKNOWN;
2373 _cg_fprofile = CG_PROFILE_UNKNOWN;
2374 _cg_gprofile = CG_PROFILE_UNKNOWN;
2375 if (_default_caps._ultimate_vprofile == 0 || _default_caps._ultimate_vprofile == CG_PROFILE_UNKNOWN) {
2376 if (basic_shaders_only) {
2377 _default_caps._active_vprofile = CG_PROFILE_ARBVP1;
2378 _default_caps._active_fprofile = CG_PROFILE_ARBFP1;
2379 _default_caps._active_gprofile = CG_PROFILE_UNKNOWN;
2381 _default_caps._active_vprofile = CG_PROFILE_UNKNOWN;
2382 _default_caps._active_fprofile = CG_PROFILE_UNKNOWN;
2383 _default_caps._active_gprofile = CG_PROFILE_UNKNOWN;
2385 _default_caps._ultimate_vprofile = cgGetProfile(
"glslv");
2386 _default_caps._ultimate_fprofile = cgGetProfile(
"glslf");
2387 _default_caps._ultimate_gprofile = cgGetProfile(
"glslg");
2388 if (_default_caps._ultimate_gprofile == CG_PROFILE_UNKNOWN) {
2389 _default_caps._ultimate_gprofile = cgGetProfile(
"gp4gp");
2401 _text._separate = sfile._separate;
2403 if (sfile._separate) {
2404 if (_language == SL_none) {
2406 <<
"No shader language was specified!\n";
2410 if (!sfile._vertex.empty() &&
2411 !do_read_source(_text._vertex, sfile._vertex, record)) {
2414 if (!sfile._fragment.empty() &&
2415 !do_read_source(_text._fragment, sfile._fragment, record)) {
2418 if (!sfile._geometry.empty() &&
2419 !do_read_source(_text._geometry, sfile._geometry, record)) {
2422 if (!sfile._tess_control.empty() &&
2423 !do_read_source(_text._tess_control, sfile._tess_control, record)) {
2426 if (!sfile._tess_evaluation.empty() &&
2427 !do_read_source(_text._tess_evaluation, sfile._tess_evaluation, record)) {
2430 if (!sfile._compute.empty() &&
2431 !do_read_source(_text._compute, sfile._compute, record)) {
2437 if (!do_read_source(_text._shared, sfile._shared, record)) {
2440 _fullpath = _source_files[0];
2444 if (_language == SL_none) {
2448 if (header ==
"//Cg") {
2452 <<
"Unable to determine shader language of " << sfile._shared <<
"\n";
2455 }
else if (_language == SL_GLSL) {
2457 <<
"GLSL shaders must have separate shader bodies!\n";
2462 if (_language == SL_Cg) {
2464 ShaderCaps caps = _default_caps;
2465 cg_get_profile_from_header(caps);
2467 if (!cg_analyze_shader(caps)) {
2469 <<
"Shader encountered an error.\n";
2474 <<
"Tried to load Cg shader, but no Cg support is enabled.\n";
2478 <<
"Shader is not in a supported shader-language.\n";
2493 _filename = ShaderFile(
"created-shader");
2495 _text._separate = sbody._separate;
2497 if (sbody._separate) {
2498 if (_language == SL_none) {
2500 <<
"No shader language was specified!\n";
2504 if (!sbody._vertex.empty() &&
2505 !do_load_source(_text._vertex, sbody._vertex, record)) {
2508 if (!sbody._fragment.empty() &&
2509 !do_load_source(_text._fragment, sbody._fragment, record)) {
2512 if (!sbody._geometry.empty() &&
2513 !do_load_source(_text._geometry, sbody._geometry, record)) {
2516 if (!sbody._tess_control.empty() &&
2517 !do_load_source(_text._tess_control, sbody._tess_control, record)) {
2520 if (!sbody._tess_evaluation.empty() &&
2521 !do_load_source(_text._tess_evaluation, sbody._tess_evaluation, record)) {
2524 if (!sbody._compute.empty() &&
2525 !do_load_source(_text._compute, sbody._compute, record)) {
2530 if (!do_load_source(_text._shared, sbody._shared, record)) {
2535 if (_language == SL_none) {
2539 if (header ==
"//Cg") {
2543 <<
"Unable to determine shader language of " << sbody._shared <<
"\n";
2546 }
else if (_language == SL_GLSL) {
2548 <<
"GLSL shaders must have separate shader bodies!\n";
2553 if (_language == SL_Cg) {
2555 ShaderCaps caps = _default_caps;
2556 cg_get_profile_from_header(caps);
2558 if (!cg_analyze_shader(caps)) {
2560 <<
"Shader encountered an error.\n";
2565 <<
"Tried to load Cg shader, but no Cg support is enabled.\n";
2569 <<
"Shader is not in a supported shader-language.\n";
2588 if (vf ==
nullptr) {
2590 <<
"Could not find shader file: " << fn <<
"\n";
2594 if (_language == SL_GLSL && glsl_preprocess) {
2595 istream *source = vf->open_read_file(
true);
2596 if (source ==
nullptr) {
2598 <<
"Could not open shader file: " << fn <<
"\n";
2604 <<
"Preprocessing shader file: " << fn <<
"\n";
2606 std::set<Filename> open_files;
2608 if (!r_preprocess_source(sstr, *source, fn, vf->get_filename(), open_files, record)) {
2609 vf->close_read_file(source);
2612 vf->close_read_file(source);
2616 shader_cat.info() <<
"Reading shader file: " << fn <<
"\n";
2618 if (!vf->read_file(into,
true)) {
2620 <<
"Could not read shader file: " << fn <<
"\n";
2625 if (record !=
nullptr) {
2629 _last_modified = std::max(_last_modified, vf->get_timestamp());
2630 _source_files.push_back(vf->get_filename());
2633 while (!into.empty() && isspace(into[into.size() - 1])) {
2634 into.resize(into.size() - 1);
2651 do_load_source(
string &into,
const std::string &source,
BamCacheRecord *record) {
2652 if (_language == SL_GLSL && glsl_preprocess) {
2654 std::set<Filename> open_files;
2655 std::ostringstream sstr;
2656 std::istringstream in(source);
2658 open_files, record)) {
2668 while (!into.empty() && isspace(into[into.size() - 1])) {
2669 into.resize(into.size() - 1);
2686 r_preprocess_include(ostream &out,
const Filename &fn,
2688 std::set<Filename> &once_files,
2691 if (depth > glsl_include_recursion_limit) {
2693 <<
"GLSL includes nested too deeply, raise glsl-include-recursion-limit"
2699 if (!source_dir.empty()) {
2700 path.prepend_directory(source_dir);
2705 if (vf ==
nullptr) {
2707 <<
"Could not find shader include: " << fn <<
"\n";
2711 Filename full_fn = vf->get_filename();
2712 if (once_files.find(full_fn) != once_files.end()) {
2717 istream *source = vf->open_read_file(
true);
2718 if (source ==
nullptr) {
2720 <<
"Could not open shader include: " << fn <<
"\n";
2724 if (record !=
nullptr) {
2727 _last_modified = std::max(_last_modified, vf->get_timestamp());
2728 _source_files.push_back(full_fn);
2736 fileno = 2048 + _included_files.size();
2741 _included_files.push_back(fn);
2743 if (shader_cat.is_debug()) {
2745 <<
"Preprocessing shader include " << fileno <<
": " << fn <<
"\n";
2748 bool result = r_preprocess_source(out, *source, fn, full_fn, once_files, record, fileno, depth);
2749 vf->close_read_file(source);
2761 r_preprocess_source(ostream &out, istream &in,
const Filename &fn,
2762 const Filename &full_fn, std::set<Filename> &once_files,
2767 int ext_google_include = 0;
2768 int ext_google_line = 0;
2769 bool had_include =
false;
2770 bool had_version =
false;
2772 bool write_line_directive = (fileno != 0);
2774 while (std::getline(in, line)) {
2780 if (!write_line_directive) {
2788 while (line[line.size() - 1] ==
'\\') {
2789 line.resize(line.size() - 1);
2792 if (std::getline(in, line2)) {
2794 if (!write_line_directive) {
2805 size_t line_comment = line.find(
"//");
2806 size_t block_comment = line.find(
"/*");
2807 if (line_comment < block_comment) {
2809 line.resize(line_comment);
2811 }
else if (block_comment < line_comment) {
2813 string line2 = line.substr(block_comment + 2);
2817 line.resize(block_comment);
2820 size_t block_end = line2.find(
"*/");
2821 while (block_end == string::npos) {
2823 if (std::getline(in, line2)) {
2824 if (!write_line_directive) {
2828 block_end = line2.find(
"*/");
2831 <<
"Expected */ before end of file " << fn <<
"\n";
2836 line += line2.substr(block_end + 2);
2840 while (!line.empty() && isspace(line[line.size() - 1])) {
2841 line.resize(line.size() - 1);
2845 if (!write_line_directive) {
2853 if (line.size() < 8 || sscanf(line.c_str(),
" # %63s", directive) != 1) {
2855 if (write_line_directive) {
2856 out <<
"#line " << lineno <<
" " << fileno <<
" // " << fn <<
"\n";
2857 write_line_directive =
false;
2859 out << line <<
"\n";
2866 if (strcmp(directive,
"pragma") == 0 &&
2867 sscanf(line.c_str(),
" # pragma %63s", pragma) == 1) {
2868 if (strcmp(pragma,
"include") == 0) {
2873 if (sscanf(line.c_str(),
" # pragma%*[ \t]include \"%2047[^\"]\" %zn", incfile, &nread) == 1
2874 && nread == line.size()) {
2879 }
else if (sscanf(line.c_str(),
" # pragma%*[ \t]include <%2047[^\"]> %zn", incfile, &nread) == 1
2880 && nread == line.size()) {
2888 <<
"Malformed #pragma include at line " << lineno
2889 <<
" of file " << fn <<
":\n " << line <<
"\n";
2895 if (!r_preprocess_include(out, incfn, source_dir, once_files, record, depth + 1)) {
2897 shader_cat.error(
false) <<
"included at line "
2898 << lineno <<
" of file " << fn <<
":\n " << line <<
"\n";
2903 write_line_directive =
true;
2907 }
else if (strcmp(pragma,
"once") == 0) {
2909 if (sscanf(line.c_str(),
" # pragma%*[ \t]once %zn", &nread) != 0 ||
2910 nread != line.size()) {
2912 <<
"Malformed #pragma once at line " << lineno
2913 <<
" of file " << fn <<
":\n " << line <<
"\n";
2918 shader_cat.warning()
2919 <<
"#pragma once in main file at line "
2920 << lineno <<
" of file " << fn
2927 if (!full_fn.empty()) {
2928 once_files.insert(full_fn);
2934 }
else if (strcmp(directive,
"endif") == 0) {
2938 write_line_directive =
true;
2941 }
else if (strcmp(directive,
"version") == 0) {
2944 }
else if (strcmp(directive,
"extension") == 0) {
2946 char extension[256];
2948 if (sscanf(line.c_str(),
" # extension%*[ \t]%255[^: \t] : %8s", extension, behavior) == 2) {
2951 if (strcmp(behavior,
"require") == 0 || strcmp(behavior,
"enable") == 0) {
2953 }
else if (strcmp(behavior,
"warn") == 0) {
2955 }
else if (strcmp(behavior,
"disable") == 0) {
2959 <<
"Extension directive specifies invalid behavior at line "
2960 << lineno <<
" of file " << fn <<
":\n " << line <<
"\n";
2964 if (strcmp(extension,
"all") == 0) {
2967 <<
"Extension directive for 'all' may only specify 'warn' or "
2968 "'disable' at line " << lineno <<
" of file " << fn
2969 <<
":\n " << line <<
"\n";
2972 ext_google_include = mode;
2973 ext_google_line = mode;
2977 }
else if (strcmp(extension,
"GL_GOOGLE_include_directive") == 0) {
2981 ext_google_include = mode;
2982 ext_google_line = mode;
2985 }
else if (strcmp(extension,
"GL_GOOGLE_cpp_style_line_directive") == 0) {
2987 ext_google_line = mode;
2992 <<
"Failed to parse extension directive at line "
2993 << lineno <<
" of file " << fn <<
":\n " << line <<
"\n";
2997 }
else if (ext_google_include > 0 && strcmp(directive,
"include") == 0) {
2999 if (ext_google_include == 1) {
3000 shader_cat.warning()
3001 <<
"Extension GL_GOOGLE_include_directive is being used at line "
3002 << lineno <<
" of file " << fn
3013 if (sscanf(line.c_str(),
" # include%*[ \t]\"%2047[^\"]\" %zn", incfile, &nread) != 1
3014 || nread != line.size()) {
3017 <<
"Malformed #include at line " << lineno
3018 <<
" of file " << fn <<
":\n " << line <<
"\n";
3026 if (!r_preprocess_include(out, incfn, source_dir, once_files, record, depth + 1)) {
3028 shader_cat.error(
false) <<
"included at line "
3029 << lineno <<
" of file " << fn <<
":\n " << line <<
"\n";
3034 write_line_directive =
true;
3038 }
else if (ext_google_line > 0 && strcmp(directive,
"line") == 0) {
3041 if (sscanf(line.c_str(),
" # line%*[ \t]%d%*[ \t]\"%2047[^\"]\" %zn", &lineno, filestr, &nread) == 2
3042 && nread == line.size()) {
3044 if (ext_google_line == 1) {
3045 shader_cat.warning()
3046 <<
"Extension GL_GOOGLE_cpp_style_line_directive is being used at line "
3047 << lineno <<
" of file " << fn
3056 fileno = 2048 + _included_files.size();
3057 _included_files.push_back(
Filename(filestr));
3059 out <<
"#line " << lineno <<
" " << fileno <<
" // " << filestr <<
"\n";
3064 if (write_line_directive) {
3065 out <<
"#line " << lineno <<
" " << fileno <<
" // " << fn <<
"\n";
3066 write_line_directive =
false;
3068 out << line <<
"\n";
3071 if (fileno == 0 && !had_version) {
3072 shader_cat.warning()
3073 <<
"GLSL shader " << fn <<
" does not contain a #version line!\n";
3084 check_modified()
const {
3088 for (it = _source_files.begin(); it != _source_files.end(); ++it) {
3092 if (vfile ==
nullptr || vfile->get_timestamp() > _last_modified) {
3106 cg_get_profile_from_header(ShaderCaps& caps) {
3120 int profilePos = buf.find(
"//Cg profile");
3121 if (profilePos >= 0) {
3123 if ((
int)buf.find(
"gp4vp") >= 0)
3124 caps._active_vprofile = cgGetProfile(
"gp4vp");
3126 if ((
int)buf.find(
"gp5vp") >= 0)
3127 caps._active_vprofile = cgGetProfile(
"gp5vp");
3129 if ((
int)buf.find(
"glslv") >= 0)
3130 caps._active_vprofile = cgGetProfile(
"glslv");
3132 if ((
int)buf.find(
"arbvp1") >= 0)
3133 caps._active_vprofile = cgGetProfile(
"arbvp1");
3135 if ((
int)buf.find(
"vp40") >= 0)
3136 caps._active_vprofile = cgGetProfile(
"vp40");
3138 if ((
int)buf.find(
"vp30") >= 0)
3139 caps._active_vprofile = cgGetProfile(
"vp30");
3141 if ((
int)buf.find(
"vp20") >= 0)
3142 caps._active_vprofile = cgGetProfile(
"vp20");
3144 if ((
int)buf.find(
"vs_1_1") >= 0)
3145 caps._active_vprofile = cgGetProfile(
"vs_1_1");
3147 if ((
int)buf.find(
"vs_2_0") >= 0)
3148 caps._active_vprofile = cgGetProfile(
"vs_2_0");
3150 if ((
int)buf.find(
"vs_2_x") >= 0)
3151 caps._active_vprofile = cgGetProfile(
"vs_2_x");
3153 if ((
int)buf.find(
"vs_3_0") >= 0)
3154 caps._active_vprofile = cgGetProfile(
"vs_3_0");
3156 if ((
int)buf.find(
"vs_4_0") >= 0)
3157 caps._active_vprofile = cgGetProfile(
"vs_4_0");
3159 if ((
int)buf.find(
"vs_5_0") >= 0)
3160 caps._active_vprofile = cgGetProfile(
"vs_5_0");
3163 if ((
int)buf.find(
"gp4fp") >= 0)
3164 caps._active_fprofile = cgGetProfile(
"gp4fp");
3166 if ((
int)buf.find(
"gp5fp") >= 0)
3167 caps._active_fprofile = cgGetProfile(
"gp5fp");
3169 if ((
int)buf.find(
"glslf") >= 0)
3170 caps._active_fprofile = cgGetProfile(
"glslf");
3172 if ((
int)buf.find(
"arbfp1") >= 0)
3173 caps._active_fprofile = cgGetProfile(
"arbfp1");
3175 if ((
int)buf.find(
"fp40") >= 0)
3176 caps._active_fprofile = cgGetProfile(
"fp40");
3178 if ((
int)buf.find(
"fp30") >= 0)
3179 caps._active_fprofile = cgGetProfile(
"fp30");
3181 if ((
int)buf.find(
"fp20") >= 0)
3182 caps._active_fprofile = cgGetProfile(
"fp20");
3184 if ((
int)buf.find(
"ps_1_1") >= 0)
3185 caps._active_fprofile = cgGetProfile(
"ps_1_1");
3187 if ((
int)buf.find(
"ps_1_2") >= 0)
3188 caps._active_fprofile = cgGetProfile(
"ps_1_2");
3190 if ((
int)buf.find(
"ps_1_3") >= 0)
3191 caps._active_fprofile = cgGetProfile(
"ps_1_3");
3193 if ((
int)buf.find(
"ps_2_0") >= 0)
3194 caps._active_fprofile = cgGetProfile(
"ps_2_0");
3196 if ((
int)buf.find(
"ps_2_x") >= 0)
3197 caps._active_fprofile = cgGetProfile(
"ps_2_x");
3199 if ((
int)buf.find(
"ps_3_0") >= 0)
3200 caps._active_fprofile = cgGetProfile(
"ps_3_0");
3202 if ((
int)buf.find(
"ps_4_0") >= 0)
3203 caps._active_fprofile = cgGetProfile(
"ps_4_0");
3205 if ((
int)buf.find(
"ps_5_0") >= 0)
3206 caps._active_fprofile = cgGetProfile(
"ps_5_0");
3209 if ((
int)buf.find(
"gp4gp") >= 0)
3210 caps._active_gprofile = cgGetProfile(
"gp4gp");
3212 if ((
int)buf.find(
"gp5gp") >= 0)
3213 caps._active_gprofile = cgGetProfile(
"gp5gp");
3215 if ((
int)buf.find(
"glslg") >= 0)
3216 caps._active_gprofile = cgGetProfile(
"glslg");
3218 if ((
int)buf.find(
"gs_4_0") >= 0)
3219 caps._active_gprofile = cgGetProfile(
"gs_4_0");
3221 if ((
int)buf.find(
"gs_5_0") >= 0)
3222 caps._active_gprofile = cgGetProfile(
"gs_5_0");
3224 }
while(_parse > lastParse);
3257 }
else if (glsl_preprocess && index >= 2048 &&
3258 (index - 2048) < (
int)_included_files.size()) {
3259 return _included_files[(size_t)index - 2048];
3262 string str = format_string(index);
3270 load(
const Filename &file, ShaderLanguage lang) {
3271 ShaderFile sfile(file);
3272 ShaderTable::const_iterator i = _load_table.find(sfile);
3273 if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
3275 if (i->second->check_modified()) {
3277 <<
"Shader " << file <<
" was modified on disk, reloading.\n";
3279 if (shader_cat.is_debug()) {
3281 <<
"Shader " << file <<
" was found in shader cache.\n";
3288 if (!shader->read(sfile)) {
3292 _load_table[sfile] = shader;
3294 if (cache_generated_shaders) {
3295 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3296 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3299 _make_table[shader->_text] = shader;
3308 load(ShaderLanguage lang,
const Filename &vertex,
3311 ShaderFile sfile(vertex, fragment, geometry, tess_control, tess_evaluation);
3312 ShaderTable::const_iterator i = _load_table.find(sfile);
3313 if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
3315 if (i->second->check_modified()) {
3317 <<
"Shader was modified on disk, reloading.\n";
3319 if (shader_cat.is_debug()) {
3321 <<
"Shader was found in shader cache.\n";
3328 if (!shader->read(sfile)) {
3332 _load_table[sfile] = shader;
3334 if (cache_generated_shaders) {
3335 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3336 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3339 _make_table[shader->_text] = shader;
3348 load_compute(ShaderLanguage lang,
const Filename &fn) {
3349 if (lang != SL_GLSL) {
3351 <<
"Only GLSL compute shaders are currently supported.\n";
3359 <<
"Could not find compute shader file: " << fn <<
"\n";
3364 sfile._separate =
true;
3365 sfile._compute = fn;
3367 ShaderTable::const_iterator i = _load_table.find(sfile);
3368 if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
3370 if (i->second->check_modified()) {
3372 <<
"Compute shader " << fn <<
" was modified on disk, reloading.\n";
3374 if (shader_cat.is_debug()) {
3376 <<
"Compute shader " << fn <<
" was found in shader cache.\n";
3384 if (record !=
nullptr) {
3385 if (record->has_data()) {
3387 <<
"Compute shader " << fn <<
" was found in disk cache.\n";
3395 if (!shader->read(sfile, record)) {
3398 _load_table[sfile] = shader;
3400 if (cache_generated_shaders) {
3401 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3402 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3405 _make_table[shader->_text] = shader;
3410 std::swap(shader->_record, record);
3412 shader->_fullpath = shader->_source_files[0];
3420 make(
string body, ShaderLanguage lang) {
3421 if (lang == SL_GLSL) {
3423 <<
"GLSL shaders must have separate shader bodies!\n";
3426 }
else if (lang == SL_none) {
3427 shader_cat.warning()
3428 <<
"Shader::make() now requires an explicit shader language. Assuming Cg.\n";
3432 if (lang == SL_Cg) {
3433 shader_cat.error() <<
"Support for Cg shaders is not enabled.\n";
3438 ShaderFile sbody(move(body));
3440 if (cache_generated_shaders) {
3441 ShaderTable::const_iterator i = _make_table.find(sbody);
3442 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3444 if (!i->second->check_modified()) {
3451 if (!shader->load(sbody)) {
3455 if (cache_generated_shaders) {
3456 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3457 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3460 _make_table[shader->_text] = shader;
3462 _make_table[std::move(sbody)] = shader;
3465 if (dump_generated_shaders) {
3467 int index = _shaders_generated ++;
3468 fns <<
"genshader" << index;
3469 string fn = fns.str();
3470 shader_cat.warning() <<
"Dumping shader: " << fn <<
"\n";
3473 s.open(fn.c_str(), std::ios::out | std::ios::trunc);
3474 s << shader->get_text();
3484 make(ShaderLanguage lang,
string vertex,
string fragment,
string geometry,
3485 string tess_control,
string tess_evaluation) {
3487 if (lang == SL_Cg) {
3488 shader_cat.error() <<
"Support for Cg shaders is not enabled.\n";
3492 if (lang == SL_none) {
3494 <<
"Shader::make() requires an explicit shader language.\n";
3498 ShaderFile sbody(move(vertex), move(fragment), move(geometry),
3499 move(tess_control), move(tess_evaluation));
3501 if (cache_generated_shaders) {
3502 ShaderTable::const_iterator i = _make_table.find(sbody);
3503 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3505 if (!i->second->check_modified()) {
3512 shader->_filename = ShaderFile(
"created-shader");
3513 if (!shader->load(sbody)) {
3517 if (cache_generated_shaders) {
3518 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3519 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3522 _make_table[shader->_text] = shader;
3524 _make_table[std::move(sbody)] = shader;
3534 make_compute(ShaderLanguage lang,
string body) {
3535 if (lang != SL_GLSL) {
3537 <<
"Only GLSL compute shaders are currently supported.\n";
3542 sbody._separate =
true;
3543 sbody._compute = move(body);
3545 if (cache_generated_shaders) {
3546 ShaderTable::const_iterator i = _make_table.find(sbody);
3547 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3549 if (!i->second->check_modified()) {
3556 shader->_filename = ShaderFile(
"created-shader");
3557 if (!shader->load(sbody)) {
3561 if (cache_generated_shaders) {
3562 ShaderTable::const_iterator i = _make_table.find(shader->_text);
3563 if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
3566 _make_table[shader->_text] = shader;
3568 _make_table[std::move(sbody)] = shader;
3588 parse_line(
string &result,
bool lt,
bool rt) {
3589 nassertv(!_text._separate);
3590 int len = _text._shared.size();
3593 while ((tail < len) && (_text._shared[tail] !=
'\n')) {
3602 while ((head < tail)&&(isspace(_text._shared[head]))) head++;
3603 while ((tail > head)&&(isspace(_text._shared[tail-1]))) tail--;
3605 result = _text._shared.substr(head, tail-head);
3614 parse_upto(
string &result,
string pattern,
bool include) {
3615 nassertv(!_text._separate);
3619 while (_parse < (
int)(_text._shared.size())) {
3626 result = _text._shared.substr(start, _parse - start);
3628 result = _text._shared.substr(start, last - start);
3637 nassertv(!_text._separate);
3638 result = _text._shared.substr(_parse, _text._shared.size() - _parse);
3646 return (
int)_text._shared.size() == _parse;
3660 return prepared_objects->enqueue_shader_future(
this);
3669 Contexts::const_iterator ci;
3670 ci = _contexts.find(prepared_objects);
3671 if (ci != _contexts.end()) {
3683 Contexts::iterator ci;
3684 ci = _contexts.find(prepared_objects);
3685 if (ci != _contexts.end()) {
3687 if (sc !=
nullptr) {
3690 _contexts.erase(ci);
3713 Contexts::const_iterator ci;
3714 ci = _contexts.find(prepared_objects);
3715 if (ci != _contexts.end()) {
3716 return (*ci).second;
3720 _contexts[prepared_objects] = tc;
3733 Contexts::iterator ci;
3734 ci = _contexts.find(prepared_objects);
3735 if (ci != _contexts.end()) {
3736 _contexts.erase(ci);
3740 nassert_raise(
"unknown PreparedGraphicsObjects");
3755 int num_freed = (int)_contexts.size();
3757 Contexts::const_iterator ci;
3758 for (ci = temp.begin(); ci != temp.end(); ++ci) {
3761 if (sc !=
nullptr) {
3776 void Shader::ShaderCaps::
3778 _supports_glsl =
false;
3781 _active_vprofile = CG_PROFILE_UNKNOWN;
3782 _active_fprofile = CG_PROFILE_UNKNOWN;
3783 _active_gprofile = CG_PROFILE_UNKNOWN;
3784 _ultimate_vprofile = CG_PROFILE_UNKNOWN;
3785 _ultimate_fprofile = CG_PROFILE_UNKNOWN;
3786 _ultimate_gprofile = CG_PROFILE_UNKNOWN;
3825 attrib->fillin(scan, manager);
3835 _language = (ShaderLanguage) scan.
get_uint8();