Skip to content

Commit 53c4486

Browse files
authored
Allow restricting to WGSL-supported builtins (#1159)
GraphicsFuzz can be used to test WGSL implementations, via translators from GLSL to WGSL (possibly via SPIR-V). But this only works for shaders that are WGSL compatible. This change adds an option to control this, and avoids generating a number of builtins that are not currently supported in the WGSL spec.
1 parent 23c2d4b commit 53c4486

32 files changed

+236
-115
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2021 The GraphicsFuzz Project Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.graphicsfuzz.common.typing;
18+
19+
import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
20+
import com.graphicsfuzz.common.util.ShaderKind;
21+
import java.util.Objects;
22+
23+
public class ShadingLanguageVersionAndKind {
24+
private final ShadingLanguageVersion shadingLanguageVersion;
25+
private final boolean isWgslCompatible;
26+
private final ShaderKind shaderKind;
27+
28+
public ShadingLanguageVersionAndKind(ShadingLanguageVersion shadingLanguageVersion,
29+
boolean isWgslCompatible, ShaderKind shaderKind) {
30+
this.shadingLanguageVersion = shadingLanguageVersion;
31+
this.isWgslCompatible = isWgslCompatible;
32+
this.shaderKind = shaderKind;
33+
}
34+
35+
@Override
36+
public boolean equals(Object that) {
37+
if (this == that) {
38+
return true;
39+
}
40+
if (that == null || getClass() != that.getClass()) {
41+
return false;
42+
}
43+
ShadingLanguageVersionAndKind thatShadingLanguageVersionAndKind =
44+
(ShadingLanguageVersionAndKind) that;
45+
return isWgslCompatible == thatShadingLanguageVersionAndKind.isWgslCompatible
46+
&& Objects.equals(shadingLanguageVersion,
47+
thatShadingLanguageVersionAndKind.shadingLanguageVersion)
48+
&& shaderKind == thatShadingLanguageVersionAndKind.shaderKind;
49+
}
50+
51+
@Override
52+
public int hashCode() {
53+
return Objects.hash(shadingLanguageVersion, isWgslCompatible, shaderKind);
54+
}
55+
}

ast/src/main/java/com/graphicsfuzz/common/typing/Typer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) {
172172
// Next, see if there is a builtin with a matching prototype.
173173
final Optional<Type> maybeMatchingBuiltinFunctionReturn =
174174
lookForMatchingFunction(functionCallExpr,
175-
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), tu.getShaderKind())
175+
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), false, tu.getShaderKind())
176176
.get(functionCallExpr.getCallee()));
177177
if (maybeMatchingBuiltinFunctionReturn.isPresent()) {
178178
types.put(functionCallExpr, maybeMatchingBuiltinFunctionReturn.get());
@@ -510,7 +510,7 @@ public Set<FunctionPrototype> getPrototypes(String name) {
510510
result.addAll(userDefinedFunctions.get(name));
511511
}
512512
final Map<String, List<FunctionPrototype>> builtins =
513-
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), tu.getShaderKind());
513+
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), false, tu.getShaderKind());
514514
if (builtins.containsKey(name)) {
515515
result.addAll(builtins.get(name));
516516
}

ast/src/main/java/com/graphicsfuzz/common/typing/TyperHelper.java

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@
4242
*/
4343
public final class TyperHelper {
4444

45-
// Maps a (shading language version, shader kind) pair to a mapping from builtin names to builtin
46-
// function prototypes.
47-
private static ConcurrentMap<ShadingLanguageVersion,
48-
ConcurrentMap<ShaderKind, Map<String, List<FunctionPrototype>>>> builtins =
45+
// Maps a shading language version + shader kind (+ WGSL compatibility) to a mapping from
46+
// builtin names to builtin function prototypes.
47+
private static ConcurrentMap<ShadingLanguageVersionAndKind, Map<String,
48+
List<FunctionPrototype>>> builtins =
4949
new ConcurrentHashMap<>();
5050

5151
private TyperHelper() {
@@ -283,44 +283,48 @@ public static Type resolveTypeOfMul(Type lhsType, Type rhsType) {
283283
* Yield the builtins available for the given shading language version and kind of shader.
284284
*
285285
* @param shadingLanguageVersion version of GLSL for which relevant builtins should be returned.
286+
* @param isWgslCompatible determines whether only builtins that work when targeting WGSL
287+
* should be included.
286288
* @param shaderKind kind of shader (e.g. fragment or compute) for which relevant builtins
287289
* should be returned.
288290
* @return a mapping from name of builtin to sequence of function prototypes.
289291
*/
290-
public static Map<String, List<FunctionPrototype>> getBuiltins(ShadingLanguageVersion
291-
shadingLanguageVersion, ShaderKind shaderKind) {
292+
public static Map<String, List<FunctionPrototype>> getBuiltins(
293+
ShadingLanguageVersion shadingLanguageVersion,
294+
boolean isWgslCompatible,
295+
ShaderKind shaderKind) {
292296

293297
assert shadingLanguageVersion != null;
294298
assert shaderKind != null;
299+
ShadingLanguageVersionAndKind key = new ShadingLanguageVersionAndKind(shadingLanguageVersion,
300+
isWgslCompatible, shaderKind);
295301

296-
if (!builtins.containsKey(shadingLanguageVersion)) {
297-
builtins.putIfAbsent(shadingLanguageVersion, new ConcurrentHashMap<>());
298-
}
299-
if (!builtins.get(shadingLanguageVersion).containsKey(shaderKind)) {
300-
builtins.get(shadingLanguageVersion).putIfAbsent(shaderKind,
301-
getBuiltinsForGlslVersion(shadingLanguageVersion, shaderKind));
302+
if (!builtins.containsKey(key)) {
303+
builtins.putIfAbsent(key,
304+
getBuiltinsForGlslVersion(shadingLanguageVersion, isWgslCompatible, shaderKind));
302305
}
303-
return Collections.unmodifiableMap(builtins.get(shadingLanguageVersion).get(shaderKind));
306+
return Collections.unmodifiableMap(builtins.get(key));
304307
}
305308

306309
private static Map<String, List<FunctionPrototype>> getBuiltinsForGlslVersion(
307-
ShadingLanguageVersion shadingLanguageVersion, ShaderKind shaderKind) {
310+
ShadingLanguageVersion shadingLanguageVersion, boolean isWgslCompatible,
311+
ShaderKind shaderKind) {
308312
Map<String, List<FunctionPrototype>> builtinsForVersion = new HashMap<>();
309313

310314
// Section numbers refer to the ESSL 3.2 specification
311315

312316
// 8.1: Angle and Trigonometric Functions
313317

314-
getBuiltinsForGlslVersionAngleAndTrigonometric(shadingLanguageVersion,
315-
builtinsForVersion);
318+
getBuiltinsForGlslVersionAngleAndTrigonometric(builtinsForVersion, shadingLanguageVersion,
319+
isWgslCompatible);
316320

317321
// 8.2: Exponential Functions
318322

319323
getBuiltinsForGlslVersionExponential(builtinsForVersion);
320324

321325
// 8.3: Common Functions
322326

323-
getBuiltinsForGlslVersionCommon(shadingLanguageVersion, builtinsForVersion);
327+
getBuiltinsForGlslVersionCommon(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);
324328

325329
// 8.4: Floating-Point Pack and Unpack Functions
326330

@@ -332,15 +336,15 @@ private static Map<String, List<FunctionPrototype>> getBuiltinsForGlslVersion(
332336

333337
// 8.6: Matrix Functions
334338

335-
getBuiltinsForGlslVersionMatrix(builtinsForVersion, shadingLanguageVersion);
339+
getBuiltinsForGlslVersionMatrix(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);
336340

337341
// 8.7: Vector Relational Functions
338342

339343
getBuiltinsForGlslVersionVectorRelational(builtinsForVersion, shadingLanguageVersion);
340344

341345
// 8.8: Integer Functions
342346

343-
getBuiltinsForGlslVersionInteger(builtinsForVersion, shadingLanguageVersion);
347+
getBuiltinsForGlslVersionInteger(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);
344348

345349
// 8.9. Texture Functions
346350
getBuiltinsForGlslVersionTexture(builtinsForVersion, shadingLanguageVersion, shaderKind);
@@ -376,10 +380,12 @@ private static Map<String, List<FunctionPrototype>> getBuiltinsForGlslVersion(
376380
*
377381
* @param builtinsForVersion the list of builtins to add prototypes to
378382
* @param shadingLanguageVersion the version of GLSL in use
383+
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
379384
*/
380385
private static void getBuiltinsForGlslVersionAngleAndTrigonometric(
386+
Map<String, List<FunctionPrototype>> builtinsForVersion,
381387
ShadingLanguageVersion shadingLanguageVersion,
382-
Map<String, List<FunctionPrototype>> builtinsForVersion) {
388+
boolean isWgslCompatible) {
383389
if (shadingLanguageVersion.supportedAngleAndTrigonometricFunctions()) {
384390
{
385391
final String name = "radians";
@@ -461,21 +467,21 @@ private static void getBuiltinsForGlslVersionAngleAndTrigonometric(
461467
}
462468
}
463469

464-
{
470+
if (!isWgslCompatible) {
465471
final String name = "asinh";
466472
for (Type t : genType()) {
467473
addBuiltin(builtinsForVersion, name, t, t);
468474
}
469475
}
470476

471-
{
477+
if (!isWgslCompatible) {
472478
final String name = "acosh";
473479
for (Type t : genType()) {
474480
addBuiltin(builtinsForVersion, name, t, t);
475481
}
476482
}
477483

478-
{
484+
if (!isWgslCompatible) {
479485
final String name = "atanh";
480486
for (Type t : genType()) {
481487
addBuiltin(builtinsForVersion, name, t, t);
@@ -674,10 +680,12 @@ private static void getBuiltinsForGlslVersionVectorRelational(
674680
*
675681
* @param builtinsForVersion the list of builtins to add prototypes to
676682
* @param shadingLanguageVersion the version of GLSL in use
683+
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
677684
*/
678685
private static void getBuiltinsForGlslVersionInteger(
679686
Map<String, List<FunctionPrototype>> builtinsForVersion,
680-
ShadingLanguageVersion shadingLanguageVersion) {
687+
ShadingLanguageVersion shadingLanguageVersion,
688+
boolean isWgslCompatible) {
681689
if (shadingLanguageVersion.supportedIntegerFunctions()) {
682690
{
683691
final String name = "uaddCarry";
@@ -713,7 +721,7 @@ private static void getBuiltinsForGlslVersionInteger(
713721
}
714722
}
715723

716-
{
724+
if (!isWgslCompatible) {
717725
final String name = "bitfieldExtract";
718726
for (Type t : igenType()) {
719727
addBuiltin(builtinsForVersion, name, t, t, BasicType.INT, BasicType.INT);
@@ -723,7 +731,7 @@ private static void getBuiltinsForGlslVersionInteger(
723731
}
724732
}
725733

726-
{
734+
if (!isWgslCompatible) {
727735
final String name = "bitfieldInsert";
728736
for (Type t : igenType()) {
729737
addBuiltin(builtinsForVersion, name, t, t, t, BasicType.INT, BasicType.INT);
@@ -753,15 +761,15 @@ private static void getBuiltinsForGlslVersionInteger(
753761
}
754762
}
755763

756-
{
764+
if (!isWgslCompatible) {
757765
final String name = "findLSB";
758766
for (int i = 0; i < igenType().size(); i++) {
759767
addBuiltin(builtinsForVersion, name, igenType().get(i), igenType().get(i));
760768
addBuiltin(builtinsForVersion, name, igenType().get(i), ugenType().get(i));
761769
}
762770
}
763771

764-
{
772+
if (!isWgslCompatible) {
765773
final String name = "findMSB";
766774
for (int i = 0; i < igenType().size(); i++) {
767775
addBuiltin(builtinsForVersion, name, igenType().get(i), igenType().get(i));
@@ -1028,10 +1036,12 @@ private static void getBuiltinsForGlslVersionShaderMemoryControl(
10281036
*
10291037
* @param builtinsForVersion the list of builtins to add prototypes to
10301038
* @param shadingLanguageVersion the version of GLSL in use
1039+
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
10311040
*/
10321041
private static void getBuiltinsForGlslVersionMatrix(
10331042
Map<String, List<FunctionPrototype>> builtinsForVersion,
1034-
ShadingLanguageVersion shadingLanguageVersion) {
1043+
ShadingLanguageVersion shadingLanguageVersion,
1044+
boolean isWgslCompatible) {
10351045
{
10361046
final String name = "matrixCompMult";
10371047
for (Type t : BasicType.allMatrixTypes()) {
@@ -1068,14 +1078,14 @@ private static void getBuiltinsForGlslVersionMatrix(
10681078
addBuiltin(builtinsForVersion, name, BasicType.MAT4X4, BasicType.MAT4X4);
10691079
}
10701080

1071-
if (shadingLanguageVersion.supportedDeterminant()) {
1081+
if (shadingLanguageVersion.supportedDeterminant() && !isWgslCompatible) {
10721082
final String name = "determinant";
10731083
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT2X2);
10741084
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT3X3);
10751085
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT4X4);
10761086
}
10771087

1078-
if (shadingLanguageVersion.supportedInverse()) {
1088+
if (shadingLanguageVersion.supportedInverse() && !isWgslCompatible) {
10791089
final String name = "inverse";
10801090
addBuiltin(builtinsForVersion, name, BasicType.MAT2X2, BasicType.MAT2X2);
10811091
addBuiltin(builtinsForVersion, name, BasicType.MAT3X3, BasicType.MAT3X3);
@@ -1214,10 +1224,12 @@ private static void getBuiltinsForGlslVersionFloatingPointPackAndUnpack(
12141224
*
12151225
* @param builtinsForVersion the list of builtins to add prototypes to
12161226
* @param shadingLanguageVersion the version of GLSL in use
1227+
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
12171228
*/
12181229
private static void getBuiltinsForGlslVersionCommon(
1230+
Map<String, List<FunctionPrototype>> builtinsForVersion,
12191231
ShadingLanguageVersion shadingLanguageVersion,
1220-
Map<String, List<FunctionPrototype>> builtinsForVersion) {
1232+
boolean isWgslCompatible) {
12211233
{
12221234
final String name = "abs";
12231235
for (Type t : genType()) {
@@ -1230,7 +1242,7 @@ private static void getBuiltinsForGlslVersionCommon(
12301242
}
12311243
}
12321244

1233-
{
1245+
if (!isWgslCompatible) {
12341246
final String name = "sign";
12351247
for (Type t : genType()) {
12361248
addBuiltin(builtinsForVersion, name, t, t);
@@ -1294,7 +1306,7 @@ private static void getBuiltinsForGlslVersionCommon(
12941306
}
12951307
}
12961308

1297-
if (shadingLanguageVersion.supportedModf()) {
1309+
if (shadingLanguageVersion.supportedModf() && !isWgslCompatible) {
12981310
{
12991311
final String name = "modf";
13001312
for (Type t : genType()) {
@@ -1506,7 +1518,7 @@ private static void getBuiltinsForGlslVersionCommon(
15061518
}
15071519
}
15081520

1509-
if (shadingLanguageVersion.supportedFrexp()) {
1521+
if (shadingLanguageVersion.supportedFrexp() && !isWgslCompatible) {
15101522
{
15111523
final String name = "frexp";
15121524
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.FLOAT,

ast/src/test/java/com/graphicsfuzz/common/typing/TyperTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,9 @@ private StringBuilder makeBuiltinsProgram(ShadingLanguageVersion shadingLanguage
12371237
}
12381238
result.append("#endif\n");
12391239
int counter = 0;
1240-
for (String name : TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind).keySet()) {
1241-
for (FunctionPrototype fp : TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
1240+
for (String name :
1241+
TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind).keySet()) {
1242+
for (FunctionPrototype fp : TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
12421243
.get(name)) {
12431244
counter++;
12441245
result.append(fp.getReturnType() + " test" + counter + "_" + fp.getName() + "(");

common/src/main/java/com/graphicsfuzz/common/util/SideEffectChecker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ private static boolean isSideEffectFreeVisitor(IAstNode node,
4343

4444
@Override
4545
public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) {
46-
if (TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
46+
if (TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
4747
.containsKey(functionCallExpr.getCallee())) {
4848
for (FunctionPrototype p :
49-
TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
49+
TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
5050
.get(functionCallExpr.getCallee())) {
5151
// We check each argument of the built-in's prototypes to see if they require lvalues -
5252
// if so, they can cause side effects.

generator/src/main/java/com/graphicsfuzz/generator/fuzzer/Fuzzer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,17 +287,21 @@ public static boolean isTooDeep(int depth, GenerationParams generationParams, IR
287287

288288
private Stream<IExprTemplate> availableTemplatesFromContext() {
289289
return Stream.concat(availableTemplatesFromScope(shadingLanguageVersion,
290+
generationParams.isWgslCompatible(),
290291
generationParams.getShaderKind(),
291292
fuzzingContext.getCurrentScope()),
292293
fuzzingContext.getFunctionPrototypes().stream().map(FunctionCallExprTemplate::new));
293294
}
294295

295296
public static Stream<IExprTemplate> availableTemplatesFromScope(
296297
ShadingLanguageVersion shadingLanguageVersion,
298+
boolean isWgslCompatible,
297299
ShaderKind shaderKind,
298300
Scope scope) {
299-
return Stream.concat(Templates.get(shadingLanguageVersion, shaderKind).stream(),
300-
scope.namesOfAllVariablesInScope()
301+
return Stream.concat(Templates.get(shadingLanguageVersion,
302+
isWgslCompatible,
303+
shaderKind)
304+
.stream(), scope.namesOfAllVariablesInScope()
301305
.stream()
302306
.map(item -> new VariableIdentifierExprTemplate(item, scope.lookupType(item),
303307
scope.lookupScopeEntry(item).hasParameterDecl())));
@@ -606,6 +610,7 @@ private static void showTemplates(String[] args) {
606610
// Call this from main to produce a list of templates
607611
List<IExprTemplate> templates = new ArrayList<>();
608612
templates.addAll(Templates.get(ShadingLanguageVersion.fromVersionString(args[0]),
613+
false,
609614
ShaderKind.fromExtension(args[1])));
610615
Collections.sort(templates, new Comparator<IExprTemplate>() {
611616
@Override

generator/src/main/java/com/graphicsfuzz/generator/fuzzer/OpaqueExpressionGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ private Optional<Expr> opaqueZeroOrOneMatrixDet(BasicType type, boolean constCon
235235
if (type != BasicType.FLOAT) {
236236
return Optional.empty();
237237
}
238-
if (!shadingLanguageVersion.supportedDeterminant()) {
238+
if (!shadingLanguageVersion.supportedDeterminant() || generationParams.isWgslCompatible()) {
239239
return Optional.empty();
240240
}
241241
// If true, we will make an upper triangular matrix - otherwise it will be lower triangular.

0 commit comments

Comments
 (0)