Skip to content

Commit

Permalink
Allow restricting to WGSL-supported builtins (#1159)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
afd authored Sep 14, 2021
1 parent 23c2d4b commit 53c4486
Show file tree
Hide file tree
Showing 32 changed files with 236 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2021 The GraphicsFuzz Project Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.graphicsfuzz.common.typing;

import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
import com.graphicsfuzz.common.util.ShaderKind;
import java.util.Objects;

public class ShadingLanguageVersionAndKind {
private final ShadingLanguageVersion shadingLanguageVersion;
private final boolean isWgslCompatible;
private final ShaderKind shaderKind;

public ShadingLanguageVersionAndKind(ShadingLanguageVersion shadingLanguageVersion,
boolean isWgslCompatible, ShaderKind shaderKind) {
this.shadingLanguageVersion = shadingLanguageVersion;
this.isWgslCompatible = isWgslCompatible;
this.shaderKind = shaderKind;
}

@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null || getClass() != that.getClass()) {
return false;
}
ShadingLanguageVersionAndKind thatShadingLanguageVersionAndKind =
(ShadingLanguageVersionAndKind) that;
return isWgslCompatible == thatShadingLanguageVersionAndKind.isWgslCompatible
&& Objects.equals(shadingLanguageVersion,
thatShadingLanguageVersionAndKind.shadingLanguageVersion)
&& shaderKind == thatShadingLanguageVersionAndKind.shaderKind;
}

@Override
public int hashCode() {
return Objects.hash(shadingLanguageVersion, isWgslCompatible, shaderKind);
}
}
4 changes: 2 additions & 2 deletions ast/src/main/java/com/graphicsfuzz/common/typing/Typer.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) {
// Next, see if there is a builtin with a matching prototype.
final Optional<Type> maybeMatchingBuiltinFunctionReturn =
lookForMatchingFunction(functionCallExpr,
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), tu.getShaderKind())
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), false, tu.getShaderKind())
.get(functionCallExpr.getCallee()));
if (maybeMatchingBuiltinFunctionReturn.isPresent()) {
types.put(functionCallExpr, maybeMatchingBuiltinFunctionReturn.get());
Expand Down Expand Up @@ -510,7 +510,7 @@ public Set<FunctionPrototype> getPrototypes(String name) {
result.addAll(userDefinedFunctions.get(name));
}
final Map<String, List<FunctionPrototype>> builtins =
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), tu.getShaderKind());
TyperHelper.getBuiltins(tu.getShadingLanguageVersion(), false, tu.getShaderKind());
if (builtins.containsKey(name)) {
result.addAll(builtins.get(name));
}
Expand Down
82 changes: 47 additions & 35 deletions ast/src/main/java/com/graphicsfuzz/common/typing/TyperHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
*/
public final class TyperHelper {

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

private TyperHelper() {
Expand Down Expand Up @@ -283,44 +283,48 @@ public static Type resolveTypeOfMul(Type lhsType, Type rhsType) {
* Yield the builtins available for the given shading language version and kind of shader.
*
* @param shadingLanguageVersion version of GLSL for which relevant builtins should be returned.
* @param isWgslCompatible determines whether only builtins that work when targeting WGSL
* should be included.
* @param shaderKind kind of shader (e.g. fragment or compute) for which relevant builtins
* should be returned.
* @return a mapping from name of builtin to sequence of function prototypes.
*/
public static Map<String, List<FunctionPrototype>> getBuiltins(ShadingLanguageVersion
shadingLanguageVersion, ShaderKind shaderKind) {
public static Map<String, List<FunctionPrototype>> getBuiltins(
ShadingLanguageVersion shadingLanguageVersion,
boolean isWgslCompatible,
ShaderKind shaderKind) {

assert shadingLanguageVersion != null;
assert shaderKind != null;
ShadingLanguageVersionAndKind key = new ShadingLanguageVersionAndKind(shadingLanguageVersion,
isWgslCompatible, shaderKind);

if (!builtins.containsKey(shadingLanguageVersion)) {
builtins.putIfAbsent(shadingLanguageVersion, new ConcurrentHashMap<>());
}
if (!builtins.get(shadingLanguageVersion).containsKey(shaderKind)) {
builtins.get(shadingLanguageVersion).putIfAbsent(shaderKind,
getBuiltinsForGlslVersion(shadingLanguageVersion, shaderKind));
if (!builtins.containsKey(key)) {
builtins.putIfAbsent(key,
getBuiltinsForGlslVersion(shadingLanguageVersion, isWgslCompatible, shaderKind));
}
return Collections.unmodifiableMap(builtins.get(shadingLanguageVersion).get(shaderKind));
return Collections.unmodifiableMap(builtins.get(key));
}

private static Map<String, List<FunctionPrototype>> getBuiltinsForGlslVersion(
ShadingLanguageVersion shadingLanguageVersion, ShaderKind shaderKind) {
ShadingLanguageVersion shadingLanguageVersion, boolean isWgslCompatible,
ShaderKind shaderKind) {
Map<String, List<FunctionPrototype>> builtinsForVersion = new HashMap<>();

// Section numbers refer to the ESSL 3.2 specification

// 8.1: Angle and Trigonometric Functions

getBuiltinsForGlslVersionAngleAndTrigonometric(shadingLanguageVersion,
builtinsForVersion);
getBuiltinsForGlslVersionAngleAndTrigonometric(builtinsForVersion, shadingLanguageVersion,
isWgslCompatible);

// 8.2: Exponential Functions

getBuiltinsForGlslVersionExponential(builtinsForVersion);

// 8.3: Common Functions

getBuiltinsForGlslVersionCommon(shadingLanguageVersion, builtinsForVersion);
getBuiltinsForGlslVersionCommon(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);

// 8.4: Floating-Point Pack and Unpack Functions

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

// 8.6: Matrix Functions

getBuiltinsForGlslVersionMatrix(builtinsForVersion, shadingLanguageVersion);
getBuiltinsForGlslVersionMatrix(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);

// 8.7: Vector Relational Functions

getBuiltinsForGlslVersionVectorRelational(builtinsForVersion, shadingLanguageVersion);

// 8.8: Integer Functions

getBuiltinsForGlslVersionInteger(builtinsForVersion, shadingLanguageVersion);
getBuiltinsForGlslVersionInteger(builtinsForVersion, shadingLanguageVersion, isWgslCompatible);

// 8.9. Texture Functions
getBuiltinsForGlslVersionTexture(builtinsForVersion, shadingLanguageVersion, shaderKind);
Expand Down Expand Up @@ -376,10 +380,12 @@ private static Map<String, List<FunctionPrototype>> getBuiltinsForGlslVersion(
*
* @param builtinsForVersion the list of builtins to add prototypes to
* @param shadingLanguageVersion the version of GLSL in use
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
*/
private static void getBuiltinsForGlslVersionAngleAndTrigonometric(
Map<String, List<FunctionPrototype>> builtinsForVersion,
ShadingLanguageVersion shadingLanguageVersion,
Map<String, List<FunctionPrototype>> builtinsForVersion) {
boolean isWgslCompatible) {
if (shadingLanguageVersion.supportedAngleAndTrigonometricFunctions()) {
{
final String name = "radians";
Expand Down Expand Up @@ -461,21 +467,21 @@ private static void getBuiltinsForGlslVersionAngleAndTrigonometric(
}
}

{
if (!isWgslCompatible) {
final String name = "asinh";
for (Type t : genType()) {
addBuiltin(builtinsForVersion, name, t, t);
}
}

{
if (!isWgslCompatible) {
final String name = "acosh";
for (Type t : genType()) {
addBuiltin(builtinsForVersion, name, t, t);
}
}

{
if (!isWgslCompatible) {
final String name = "atanh";
for (Type t : genType()) {
addBuiltin(builtinsForVersion, name, t, t);
Expand Down Expand Up @@ -674,10 +680,12 @@ private static void getBuiltinsForGlslVersionVectorRelational(
*
* @param builtinsForVersion the list of builtins to add prototypes to
* @param shadingLanguageVersion the version of GLSL in use
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
*/
private static void getBuiltinsForGlslVersionInteger(
Map<String, List<FunctionPrototype>> builtinsForVersion,
ShadingLanguageVersion shadingLanguageVersion) {
ShadingLanguageVersion shadingLanguageVersion,
boolean isWgslCompatible) {
if (shadingLanguageVersion.supportedIntegerFunctions()) {
{
final String name = "uaddCarry";
Expand Down Expand Up @@ -713,7 +721,7 @@ private static void getBuiltinsForGlslVersionInteger(
}
}

{
if (!isWgslCompatible) {
final String name = "bitfieldExtract";
for (Type t : igenType()) {
addBuiltin(builtinsForVersion, name, t, t, BasicType.INT, BasicType.INT);
Expand All @@ -723,7 +731,7 @@ private static void getBuiltinsForGlslVersionInteger(
}
}

{
if (!isWgslCompatible) {
final String name = "bitfieldInsert";
for (Type t : igenType()) {
addBuiltin(builtinsForVersion, name, t, t, t, BasicType.INT, BasicType.INT);
Expand Down Expand Up @@ -753,15 +761,15 @@ private static void getBuiltinsForGlslVersionInteger(
}
}

{
if (!isWgslCompatible) {
final String name = "findLSB";
for (int i = 0; i < igenType().size(); i++) {
addBuiltin(builtinsForVersion, name, igenType().get(i), igenType().get(i));
addBuiltin(builtinsForVersion, name, igenType().get(i), ugenType().get(i));
}
}

{
if (!isWgslCompatible) {
final String name = "findMSB";
for (int i = 0; i < igenType().size(); i++) {
addBuiltin(builtinsForVersion, name, igenType().get(i), igenType().get(i));
Expand Down Expand Up @@ -1028,10 +1036,12 @@ private static void getBuiltinsForGlslVersionShaderMemoryControl(
*
* @param builtinsForVersion the list of builtins to add prototypes to
* @param shadingLanguageVersion the version of GLSL in use
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
*/
private static void getBuiltinsForGlslVersionMatrix(
Map<String, List<FunctionPrototype>> builtinsForVersion,
ShadingLanguageVersion shadingLanguageVersion) {
ShadingLanguageVersion shadingLanguageVersion,
boolean isWgslCompatible) {
{
final String name = "matrixCompMult";
for (Type t : BasicType.allMatrixTypes()) {
Expand Down Expand Up @@ -1068,14 +1078,14 @@ private static void getBuiltinsForGlslVersionMatrix(
addBuiltin(builtinsForVersion, name, BasicType.MAT4X4, BasicType.MAT4X4);
}

if (shadingLanguageVersion.supportedDeterminant()) {
if (shadingLanguageVersion.supportedDeterminant() && !isWgslCompatible) {
final String name = "determinant";
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT2X2);
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT3X3);
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.MAT4X4);
}

if (shadingLanguageVersion.supportedInverse()) {
if (shadingLanguageVersion.supportedInverse() && !isWgslCompatible) {
final String name = "inverse";
addBuiltin(builtinsForVersion, name, BasicType.MAT2X2, BasicType.MAT2X2);
addBuiltin(builtinsForVersion, name, BasicType.MAT3X3, BasicType.MAT3X3);
Expand Down Expand Up @@ -1214,10 +1224,12 @@ private static void getBuiltinsForGlslVersionFloatingPointPackAndUnpack(
*
* @param builtinsForVersion the list of builtins to add prototypes to
* @param shadingLanguageVersion the version of GLSL in use
* @param isWgslCompatible determines whether to restrict to builtins that WGSL also supports
*/
private static void getBuiltinsForGlslVersionCommon(
Map<String, List<FunctionPrototype>> builtinsForVersion,
ShadingLanguageVersion shadingLanguageVersion,
Map<String, List<FunctionPrototype>> builtinsForVersion) {
boolean isWgslCompatible) {
{
final String name = "abs";
for (Type t : genType()) {
Expand All @@ -1230,7 +1242,7 @@ private static void getBuiltinsForGlslVersionCommon(
}
}

{
if (!isWgslCompatible) {
final String name = "sign";
for (Type t : genType()) {
addBuiltin(builtinsForVersion, name, t, t);
Expand Down Expand Up @@ -1294,7 +1306,7 @@ private static void getBuiltinsForGlslVersionCommon(
}
}

if (shadingLanguageVersion.supportedModf()) {
if (shadingLanguageVersion.supportedModf() && !isWgslCompatible) {
{
final String name = "modf";
for (Type t : genType()) {
Expand Down Expand Up @@ -1506,7 +1518,7 @@ private static void getBuiltinsForGlslVersionCommon(
}
}

if (shadingLanguageVersion.supportedFrexp()) {
if (shadingLanguageVersion.supportedFrexp() && !isWgslCompatible) {
{
final String name = "frexp";
addBuiltin(builtinsForVersion, name, BasicType.FLOAT, BasicType.FLOAT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1237,8 +1237,9 @@ private StringBuilder makeBuiltinsProgram(ShadingLanguageVersion shadingLanguage
}
result.append("#endif\n");
int counter = 0;
for (String name : TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind).keySet()) {
for (FunctionPrototype fp : TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
for (String name :
TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind).keySet()) {
for (FunctionPrototype fp : TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
.get(name)) {
counter++;
result.append(fp.getReturnType() + " test" + counter + "_" + fp.getName() + "(");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ private static boolean isSideEffectFreeVisitor(IAstNode node,

@Override
public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) {
if (TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
if (TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
.containsKey(functionCallExpr.getCallee())) {
for (FunctionPrototype p :
TyperHelper.getBuiltins(shadingLanguageVersion, shaderKind)
TyperHelper.getBuiltins(shadingLanguageVersion, false, shaderKind)
.get(functionCallExpr.getCallee())) {
// We check each argument of the built-in's prototypes to see if they require lvalues -
// if so, they can cause side effects.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,21 @@ public static boolean isTooDeep(int depth, GenerationParams generationParams, IR

private Stream<IExprTemplate> availableTemplatesFromContext() {
return Stream.concat(availableTemplatesFromScope(shadingLanguageVersion,
generationParams.isWgslCompatible(),
generationParams.getShaderKind(),
fuzzingContext.getCurrentScope()),
fuzzingContext.getFunctionPrototypes().stream().map(FunctionCallExprTemplate::new));
}

public static Stream<IExprTemplate> availableTemplatesFromScope(
ShadingLanguageVersion shadingLanguageVersion,
boolean isWgslCompatible,
ShaderKind shaderKind,
Scope scope) {
return Stream.concat(Templates.get(shadingLanguageVersion, shaderKind).stream(),
scope.namesOfAllVariablesInScope()
return Stream.concat(Templates.get(shadingLanguageVersion,
isWgslCompatible,
shaderKind)
.stream(), scope.namesOfAllVariablesInScope()
.stream()
.map(item -> new VariableIdentifierExprTemplate(item, scope.lookupType(item),
scope.lookupScopeEntry(item).hasParameterDecl())));
Expand Down Expand Up @@ -606,6 +610,7 @@ private static void showTemplates(String[] args) {
// Call this from main to produce a list of templates
List<IExprTemplate> templates = new ArrayList<>();
templates.addAll(Templates.get(ShadingLanguageVersion.fromVersionString(args[0]),
false,
ShaderKind.fromExtension(args[1])));
Collections.sort(templates, new Comparator<IExprTemplate>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ private Optional<Expr> opaqueZeroOrOneMatrixDet(BasicType type, boolean constCon
if (type != BasicType.FLOAT) {
return Optional.empty();
}
if (!shadingLanguageVersion.supportedDeterminant()) {
if (!shadingLanguageVersion.supportedDeterminant() || generationParams.isWgslCompatible()) {
return Optional.empty();
}
// If true, we will make an upper triangular matrix - otherwise it will be lower triangular.
Expand Down
Loading

0 comments on commit 53c4486

Please sign in to comment.