Skip to content

Commit 7e518d0

Browse files
authored
Added support for keeping comments (#3538)
1 parent b0d32c0 commit 7e518d0

File tree

3 files changed

+134
-24
lines changed

3 files changed

+134
-24
lines changed

examples/06-bump/fs_bump.sc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
$input v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0// in...
1+
$input v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0 // in...
22

33
/*
44
* Copyright 2011-2025 Branimir Karadzic. All rights reserved.

tools/shaderc/shaderc.cpp

Lines changed: 132 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
24118
namespace 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), "\nvec4 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)

tools/shaderc/shaderc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ namespace bgfx
9494
bool disasm;
9595
bool raw;
9696
bool preprocessOnly;
97+
bool keepComments;
9798
bool depends;
9899

99100
bool debugInformation;

0 commit comments

Comments
 (0)