[WHLSL] Hook up common texture functions
[WebKit-https.git] / Source / WebCore / Modules / webgpu / WHLSL / WHLSLPrepare.cpp
1 /*
2  * Copyright (C) 2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WHLSLPrepare.h"
28
29 #if ENABLE(WEBGPU)
30
31 #include "WHLSLASTDumper.h"
32 #include "WHLSLAutoInitializeVariables.h"
33 #include "WHLSLCheckDuplicateFunctions.h"
34 #include "WHLSLCheckTextureReferences.h"
35 #include "WHLSLChecker.h"
36 #include "WHLSLComputeDimensions.h"
37 #include "WHLSLFunctionStageChecker.h"
38 #include "WHLSLHighZombieFinder.h"
39 #include "WHLSLLiteralTypeChecker.h"
40 #include "WHLSLMetalCodeGenerator.h"
41 #include "WHLSLNameResolver.h"
42 #include "WHLSLParser.h"
43 #include "WHLSLPreserveVariableLifetimes.h"
44 #include "WHLSLProgram.h"
45 #include "WHLSLPropertyResolver.h"
46 #include "WHLSLRecursionChecker.h"
47 #include "WHLSLRecursiveTypeChecker.h"
48 #include "WHLSLSemanticMatcher.h"
49 #include "WHLSLStandardLibrary.h"
50 #include "WHLSLStatementBehaviorChecker.h"
51 #include "WHLSLSynthesizeArrayOperatorLength.h"
52 #include "WHLSLSynthesizeConstructors.h"
53 #include "WHLSLSynthesizeEnumerationFunctions.h"
54 #include "WHLSLSynthesizeStructureAccessors.h"
55 #include <wtf/Optional.h>
56
57 namespace WebCore {
58
59 namespace WHLSL {
60
61 static constexpr bool dumpASTBeforeEachPass = false;
62 static constexpr bool dumpASTAfterParsing = false;
63 static constexpr bool dumpASTAtEnd = false;
64 static constexpr bool alwaysDumpPassFailures = false;
65 static constexpr bool dumpPassFailure = dumpASTBeforeEachPass || dumpASTAfterParsing || dumpASTAtEnd || alwaysDumpPassFailures;
66
67 static bool dumpASTIfNeeded(bool shouldDump, Program& program, const char* message)
68 {
69     if (shouldDump) {
70         dataLogLn(message);
71         dumpAST(program);
72         return true;
73     }
74
75     return false;
76 }
77
78 static bool dumpASTAfterParsingIfNeeded(Program& program)
79 {
80     return dumpASTIfNeeded(dumpASTAfterParsing, program, "AST after parsing");
81 }
82
83 static bool dumpASTBetweenEachPassIfNeeded(Program& program, const char* message)
84 {
85     return dumpASTIfNeeded(dumpASTBeforeEachPass, program, message);
86 }
87
88 static bool dumpASTAtEndIfNeeded(Program& program)
89 {
90     return dumpASTIfNeeded(dumpASTAtEnd, program, "AST at end");
91 }
92
93 #define RUN_PASS(pass, ...) \
94     do { \
95         dumpASTBetweenEachPassIfNeeded(program, "AST before " # pass); \
96         if (!pass(__VA_ARGS__)) { \
97             if (dumpPassFailure) \
98                 dataLogLn("failed pass: " # pass); \
99             return WTF::nullopt; \
100         } \
101     } while (0)
102     
103
104 static Optional<Program> prepareShared(String& whlslSource)
105 {
106     Program program;
107     Parser parser;
108     auto standardLibrary = String::fromUTF8(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary));
109     auto parseStdLibFailure = parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary);
110     if (!ASSERT_DISABLED && parseStdLibFailure) {
111         dataLogLn("failed to parse the standard library: ", *parseStdLibFailure);
112         RELEASE_ASSERT_NOT_REACHED();
113     }
114     if (auto parseFailure = parser.parse(program, whlslSource, Parser::Mode::User)) {
115         if (dumpPassFailure)
116             dataLogLn("failed to parse the program: ", *parseFailure);
117         return WTF::nullopt;
118     }
119
120     if (!dumpASTBetweenEachPassIfNeeded(program, "AST after parsing"))
121         dumpASTAfterParsingIfNeeded(program);
122
123     NameResolver nameResolver(program.nameContext());
124     RUN_PASS(resolveNamesInTypes, program, nameResolver);
125     RUN_PASS(checkRecursiveTypes, program);
126     RUN_PASS(synthesizeStructureAccessors, program);
127     RUN_PASS(synthesizeEnumerationFunctions, program);
128     RUN_PASS(synthesizeArrayOperatorLength, program);
129     RUN_PASS(resolveTypeNamesInFunctions, program, nameResolver);
130     RUN_PASS(synthesizeConstructors, program);
131     RUN_PASS(resolveCallsInFunctions, program, nameResolver);
132     RUN_PASS(checkDuplicateFunctions, program);
133
134     RUN_PASS(check, program);
135
136     checkLiteralTypes(program);
137     RUN_PASS(checkTextureReferences, program);
138     RUN_PASS(autoInitializeVariables, program);
139     resolveProperties(program);
140     findHighZombies(program);
141     RUN_PASS(checkStatementBehavior, program);
142     RUN_PASS(checkRecursion, program);
143     RUN_PASS(checkFunctionStages, program);
144     preserveVariableLifetimes(program);
145
146     dumpASTAtEndIfNeeded(program);
147
148     return program;
149 }
150
151 Optional<RenderPrepareResult> prepare(String& whlslSource, RenderPipelineDescriptor& renderPipelineDescriptor)
152 {
153     auto program = prepareShared(whlslSource);
154     if (!program)
155         return WTF::nullopt;
156     auto matchedSemantics = matchSemantics(*program, renderPipelineDescriptor);
157     if (!matchedSemantics)
158         return WTF::nullopt;
159
160     auto generatedCode = Metal::generateMetalCode(*program, WTFMove(*matchedSemantics), renderPipelineDescriptor.layout);
161
162     RenderPrepareResult result;
163     result.metalSource = WTFMove(generatedCode.metalSource);
164     result.mangledVertexEntryPointName = WTFMove(generatedCode.mangledVertexEntryPointName);
165     result.mangledFragmentEntryPointName = WTFMove(generatedCode.mangledFragmentEntryPointName);
166     return result;
167 }
168
169 Optional<ComputePrepareResult> prepare(String& whlslSource, ComputePipelineDescriptor& computePipelineDescriptor)
170 {
171     auto program = prepareShared(whlslSource);
172     if (!program)
173         return WTF::nullopt;
174     auto matchedSemantics = matchSemantics(*program, computePipelineDescriptor);
175     if (!matchedSemantics)
176         return WTF::nullopt;
177     auto computeDimensions = WHLSL::computeDimensions(*program, *matchedSemantics->shader);
178     if (!computeDimensions)
179         return WTF::nullopt;
180
181     auto generatedCode = Metal::generateMetalCode(*program, WTFMove(*matchedSemantics), computePipelineDescriptor.layout);
182
183     ComputePrepareResult result;
184     result.metalSource = WTFMove(generatedCode.metalSource);
185     result.mangledEntryPointName = WTFMove(generatedCode.mangledEntryPointName);
186     result.computeDimensions = WTFMove(*computeDimensions);
187     return result;
188 }
189
190 } // namespace WHLSL
191
192 } // namespace WebCore
193
194 #endif // ENABLE(WEBGPU)