@@ -21,6 +21,100 @@ extern "C"
2121#define BGFX_SHADERC_VERSION_MAJOR 1
2222#define BGFX_SHADERC_VERSION_MINOR 18
2323
24+ namespace bx
25+ {
26+ // / Find substring in string. Only match substrings that appear outside C/C++ style comment blocks.
27+ const char * strFindUncommented (const char * _str, int32_t _strMax, const char * _find, int32_t _findMax)
28+ {
29+ int32_t i = 0 ;
30+ bool inBlock = false ; // inside C style comment.
31+ bool inLine = false ; // inside C++ style comment.
32+
33+ while (i < _strMax)
34+ {
35+ if (!inBlock && !inLine)
36+ {
37+ // Look for comment blocks.
38+ if (i + 1 < _strMax && ' /' == _str[i] && ' /' == _str[i + 1 ])
39+ {
40+ inLine = true ;
41+ i += 2 ;
42+ continue ;
43+ }
44+
45+ if (i + 1 < _strMax && ' /' == _str[i] && ' *' == _str[i + 1 ])
46+ {
47+ inBlock = true ;
48+ i += 2 ;
49+ continue ;
50+ }
51+
52+ // Outside comment block.
53+ if (i + _findMax > _strMax)
54+ {
55+ return NULL ;
56+ }
57+ else
58+ {
59+ if (0 == strCmp (_str + i, _find, _findMax) )
60+ {
61+ return _str + i;
62+ }
63+ }
64+
65+ ++i;
66+ }
67+ else if (inBlock)
68+ {
69+ if (i + 1 < _strMax && ' *' == _str[i] && ' /' == _str[i + 1 ])
70+ {
71+ inBlock = false ;
72+ i += 2 ;
73+ }
74+ else
75+ {
76+ ++i;
77+ }
78+ }
79+ else if (inLine)
80+ {
81+ if (' \n ' == _str[i])
82+ {
83+ inLine = false ;
84+ }
85+
86+ ++i;
87+ }
88+ else
89+ {
90+ ++i;
91+ }
92+ }
93+
94+ return NULL ;
95+ }
96+
97+ bx::StringView strFindUncommented (const bx::StringView &_str, const bx::StringView& _find, int32_t _num = INT32_MAX)
98+ {
99+ int32_t len = min (_find.getLength (), _num);
100+
101+ const char * ptr = strFindUncommented (
102+ _str.getPtr ()
103+ , _str.getLength ()
104+ , _find.getPtr ()
105+ , len
106+ );
107+
108+ if (NULL == ptr)
109+ {
110+ return bx::StringView (_str.getTerm (), _str.getTerm () );
111+ }
112+
113+ return bx::StringView (ptr, len);
114+ }
115+
116+ }
117+
24118namespace bgfx
25119{
26120 bool g_verbose = false ;
@@ -373,6 +467,7 @@ namespace bgfx
373467 , disasm(false )
374468 , raw(false )
375469 , preprocessOnly(false )
470+ , keepComments(false )
376471 , depends(false )
377472 , debugInformation(false )
378473 , avoidFlowControl(false )
@@ -398,6 +493,7 @@ namespace bgfx
398493 " \t disasm: %s\n "
399494 " \t raw: %s\n "
400495 " \t preprocessOnly: %s\n "
496+ " \t keepComments: %s\n "
401497 " \t depends: %s\n "
402498 " \t debugInformation: %s\n "
403499 " \t avoidFlowControl: %s\n "
@@ -418,6 +514,7 @@ namespace bgfx
418514 , disasm ? " true" : " false"
419515 , raw ? " true" : " false"
420516 , preprocessOnly ? " true" : " false"
517+ , keepComments ? " true" : " false"
421518 , depends ? " true" : " false"
422519 , debugInformation ? " true" : " false"
423520 , avoidFlowControl ? " true" : " false"
@@ -756,6 +853,7 @@ namespace bgfx
756853 , m_scratchPos(0 )
757854 , m_fgetsPos(0 )
758855 , m_messageWriter(_messageWriter)
856+ , m_keepCommentsTag(NULL )
759857 {
760858 m_tagptr->tag = FPPTAG_USERDATA;
761859 m_tagptr->data = this ;
@@ -789,6 +887,10 @@ namespace bgfx
789887 m_tagptr->data = scratch (_filePath);
790888 m_tagptr++;
791889
890+ m_tagptr->tag = FPPTAG_KEEPCOMMENTS;
891+ m_tagptr->data = (void *)0 ;
892+ m_keepCommentsTag = m_tagptr++;
893+
792894 if (!_essl)
793895 {
794896 m_default = " #define lowp\n #define mediump\n #define highp\n " ;
@@ -856,6 +958,11 @@ namespace bgfx
856958 m_depends += _fileName;
857959 }
858960
961+ void setKeepComments (bool keep)
962+ {
963+ m_keepCommentsTag->data = (void *)keep;
964+ }
965+
859966 bool run (const char * _input)
860967 {
861968 m_fgetsPos = 0 ;
@@ -946,6 +1053,7 @@ namespace bgfx
9461053 uint32_t m_scratchPos;
9471054 uint32_t m_fgetsPos;
9481055 bx::WriterI* m_messageWriter;
1056+ fppTag* m_keepCommentsTag;
9491057 };
9501058
9511059 typedef std::vector<std::string> InOut;
@@ -1083,6 +1191,7 @@ namespace bgfx
10831191
10841192 bx::printf (
10851193 " --preprocess Only pre-process.\n "
1194+ " --keepcomments Do not discard comments.\n "
10861195 " --define <defines> Add defines to preprocessor. (Semicolon-separated)\n "
10871196 " --raw Do not process shader. No preprocessor, and no glsl-optimizer. (GLSL only)\n "
10881197 " --type <type> Shader type. Can be 'vertex', 'fragment, or 'compute'.\n "
@@ -1461,9 +1570,7 @@ namespace bgfx
14611570
14621571 if (!raw)
14631572 {
1464- // To avoid commented code being recognized as used feature,
1465- // first preprocess pass is used to strip all comments before
1466- // substituting code.
1573+ preprocessor.setKeepComments (_options.keepComments );
14671574 bool ok = preprocessor.run (data);
14681575 delete [] data;
14691576
@@ -1588,7 +1695,7 @@ namespace bgfx
15881695 }
15891696 else if (' c' == _options.shaderType ) // Compute
15901697 {
1591- bx::StringView entry = bx::strFind (input, " void main()" );
1698+ bx::StringView entry = bx::strFindUncommented (input, " void main()" );
15921699 if (entry.isEmpty () )
15931700 {
15941701 bx::write (_messageWriter, &messageErr, " Shader entry point 'void main()' is not found.\n " );
@@ -1631,10 +1738,10 @@ namespace bgfx
16311738
16321739 uint32_t arg = 0 ;
16331740
1634- const bool hasLocalInvocationID = !bx::strFind (input, " gl_LocalInvocationID" ).isEmpty ();
1635- const bool hasLocalInvocationIndex = !bx::strFind (input, " gl_LocalInvocationIndex" ).isEmpty ();
1636- const bool hasGlobalInvocationID = !bx::strFind (input, " gl_GlobalInvocationID" ).isEmpty ();
1637- const bool hasWorkGroupID = !bx::strFind (input, " gl_WorkGroupID" ).isEmpty ();
1741+ const bool hasLocalInvocationID = !bx::strFindUncommented (input, " gl_LocalInvocationID" ).isEmpty ();
1742+ const bool hasLocalInvocationIndex = !bx::strFindUncommented (input, " gl_LocalInvocationIndex" ).isEmpty ();
1743+ const bool hasGlobalInvocationID = !bx::strFindUncommented (input, " gl_GlobalInvocationID" ).isEmpty ();
1744+ const bool hasWorkGroupID = !bx::strFindUncommented (input, " gl_WorkGroupID" ).isEmpty ();
16381745
16391746 if (hasLocalInvocationID)
16401747 {
@@ -1765,7 +1872,7 @@ namespace bgfx
17651872 else // Vertex/Fragment
17661873 {
17671874 bx::StringView shader (input);
1768- bx::StringView entry = bx::strFind (shader, " void main()" );
1875+ bx::StringView entry = bx::strFindUncommented (shader, " void main()" );
17691876 if (entry.isEmpty () )
17701877 {
17711878 bx::write (_messageWriter, &messageErr, " Shader entry point 'void main()' is not found.\n " );
@@ -1789,14 +1896,14 @@ namespace bgfx
17891896 if (profile->lang == ShadingLang::ESSL
17901897 && profile->id >= 300 )
17911898 {
1792- const bool hasFragColor = !bx::strFind (input, " gl_FragColor" ).isEmpty ();
1899+ const bool hasFragColor = !bx::strFindUncommented (input, " gl_FragColor" ).isEmpty ();
17931900 bool hasFragData[8 ] = {};
17941901 uint32_t numFragData = 0 ;
17951902 for (uint32_t ii = 0 ; ii < BX_COUNTOF (hasFragData); ++ii)
17961903 {
17971904 char temp[32 ];
17981905 bx::snprintf (temp, BX_COUNTOF (temp), " gl_FragData[%d]" , ii);
1799- hasFragData[ii] = !bx::strFind (input, temp).isEmpty ();
1906+ hasFragData[ii] = !bx::strFindUncommented (input, temp).isEmpty ();
18001907 numFragData += hasFragData[ii];
18011908 }
18021909 if (hasFragColor)
@@ -1897,17 +2004,17 @@ namespace bgfx
18972004
18982005 if (' f' == _options.shaderType )
18992006 {
1900- bx::StringView insert = bx::strFind (bx::StringView (entry.getPtr (), shader.getTerm () ), " {" );
2007+ bx::StringView insert = bx::strFindUncommented (bx::StringView (entry.getPtr (), shader.getTerm () ), " {" );
19012008 if (!insert.isEmpty () )
19022009 {
19032010 insert = strInsert (const_cast <char *>(insert.getPtr ()+1 ), " \n vec4 bgfx_VoidFrag = vec4_splat(0.0);\n " );
19042011 }
19052012
1906- const bool hasFragColor = !bx::strFind (input, " gl_FragColor" ).isEmpty ();
1907- const bool hasFragCoord = !bx::strFind (input, " gl_FragCoord" ).isEmpty () || profile->id >= 400 ;
1908- const bool hasFragDepth = !bx::strFind (input, " gl_FragDepth" ).isEmpty ();
1909- const bool hasFrontFacing = !bx::strFind (input, " gl_FrontFacing" ).isEmpty ();
1910- const bool hasPrimitiveId = !bx::strFind (input, " gl_PrimitiveID" ).isEmpty () && BGFX_CAPS_PRIMITIVE_ID;
2013+ const bool hasFragColor = !bx::strFindUncommented (input, " gl_FragColor" ).isEmpty ();
2014+ const bool hasFragCoord = !bx::strFindUncommented (input, " gl_FragCoord" ).isEmpty () || profile->id >= 400 ;
2015+ const bool hasFragDepth = !bx::strFindUncommented (input, " gl_FragDepth" ).isEmpty ();
2016+ const bool hasFrontFacing = !bx::strFindUncommented (input, " gl_FrontFacing" ).isEmpty ();
2017+ const bool hasPrimitiveId = !bx::strFindUncommented (input, " gl_PrimitiveID" ).isEmpty () && BGFX_CAPS_PRIMITIVE_ID;
19112018
19122019 if (!hasPrimitiveId)
19132020 {
@@ -1920,7 +2027,7 @@ namespace bgfx
19202027 {
19212028 char temp[32 ];
19222029 bx::snprintf (temp, BX_COUNTOF (temp), " gl_FragData[%d]" , ii);
1923- hasFragData[ii] = !bx::strFind (input, temp).isEmpty ();
2030+ hasFragData[ii] = !bx::strFindUncommented (input, temp).isEmpty ();
19242031 numFragData += hasFragData[ii];
19252032 }
19262033
@@ -2045,12 +2152,12 @@ namespace bgfx
20452152 }
20462153 else if (' v' == _options.shaderType )
20472154 {
2048- const bool hasVertexId = !bx::strFind (input, " gl_VertexID" ).isEmpty ();
2049- const bool hasInstanceId = !bx::strFind (input, " gl_InstanceID" ).isEmpty ();
2050- const bool hasViewportId = !bx::strFind (input, " gl_ViewportIndex" ).isEmpty ();
2051- const bool hasLayerId = !bx::strFind (input, " gl_Layer" ).isEmpty ();
2155+ const bool hasVertexId = !bx::strFindUncommented (input, " gl_VertexID" ).isEmpty ();
2156+ const bool hasInstanceId = !bx::strFindUncommented (input, " gl_InstanceID" ).isEmpty ();
2157+ const bool hasViewportId = !bx::strFindUncommented (input, " gl_ViewportIndex" ).isEmpty ();
2158+ const bool hasLayerId = !bx::strFindUncommented (input, " gl_Layer" ).isEmpty ();
20522159
2053- bx::StringView brace = bx::strFind (bx::StringView (entry.getPtr (), shader.getTerm () ), " {" );
2160+ bx::StringView brace = bx::strFindUncommented (bx::StringView (entry.getPtr (), shader.getTerm () ), " {" );
20542161 if (!brace.isEmpty () )
20552162 {
20562163 bx::StringView block = bx::strFindBlock (bx::StringView (brace.getPtr (), shader.getTerm () ), ' {' , ' }' );
@@ -2788,10 +2895,12 @@ namespace bgfx
27882895
27892896 options.depends = cmdLine.hasArg (" depends" );
27902897 options.preprocessOnly = cmdLine.hasArg (" preprocess" );
2898+ options.keepComments = cmdLine.hasArg (" keepcomments" );
27912899 const char * includeDir = cmdLine.findOption (' i' );
27922900
27932901 BX_TRACE (" depends: %d" , options.depends );
27942902 BX_TRACE (" preprocessOnly: %d" , options.preprocessOnly );
2903+ BX_TRACE (" keepComments: %d" , options.keepComments );
27952904 BX_TRACE (" includeDir: %s" , includeDir);
27962905
27972906 for (int ii = 1 ; NULL != includeDir; ++ii)
0 commit comments