95f7ca2a5e715f52fd5badcd7a467febba8d230b
[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 "WHLSLCheckDuplicateFunctions.h"
33 #include "WHLSLChecker.h"
34 #include "WHLSLFunctionStageChecker.h"
35 #include "WHLSLHighZombieFinder.h"
36 #include "WHLSLLiteralTypeChecker.h"
37 #include "WHLSLMetalCodeGenerator.h"
38 #include "WHLSLNameResolver.h"
39 #include "WHLSLParser.h"
40 #include "WHLSLProgram.h"
41 #include "WHLSLPropertyResolver.h"
42 #include "WHLSLRecursionChecker.h"
43 #include "WHLSLRecursiveTypeChecker.h"
44 #include "WHLSLSemanticMatcher.h"
45 #include "WHLSLStandardLibrary.h"
46 #include "WHLSLStatementBehaviorChecker.h"
47 #include "WHLSLSynthesizeArrayOperatorLength.h"
48 #include "WHLSLSynthesizeConstructors.h"
49 #include "WHLSLSynthesizeEnumerationFunctions.h"
50 #include "WHLSLSynthesizeStructureAccessors.h"
51 #include <wtf/Optional.h>
52
53 namespace WebCore {
54
55 namespace WHLSL {
56
57 static constexpr bool dumpASTBeforeEachPass = false;
58 static constexpr bool dumpASTAfterParsing = false;
59 static constexpr bool dumpASTAtEnd = false;
60
61 static bool dumpASTIfNeeded(bool shouldDump, Program& program, const char* message)
62 {
63     if (shouldDump) {
64         dataLogLn(message);
65         dumpAST(program);
66         return true;
67     }
68
69     return false;
70 }
71
72 static bool dumpASTAfterParsingIfNeeded(Program& program)
73 {
74     return dumpASTIfNeeded(dumpASTAfterParsing, program, "AST after parsing");
75 }
76
77 static bool dumpASTBetweenEachPassIfNeeded(Program& program, const char* message)
78 {
79     return dumpASTIfNeeded(dumpASTBeforeEachPass, program, message);
80 }
81
82 static bool dumpASTAtEndIfNeeded(Program& program)
83 {
84     return dumpASTIfNeeded(dumpASTAtEnd, program, "AST at end");
85 }
86
87 #define RUN_PASS(pass, ...) \
88     do { \
89         dumpASTBetweenEachPassIfNeeded(program, "AST before " # pass); \
90         if (!pass(__VA_ARGS__)) \
91             return WTF::nullopt; \
92     } while (0)
93     
94
95 static Optional<Program> prepareShared(String& whlslSource)
96 {
97     Program program;
98     Parser parser;
99     auto standardLibrary = String::fromUTF8(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary));
100     auto failure = static_cast<bool>(parser.parse(program, standardLibrary, Parser::Mode::StandardLibrary));
101     ASSERT_UNUSED(failure, !failure);
102     if (parser.parse(program, whlslSource, Parser::Mode::User))
103         return WTF::nullopt;
104
105     if (!dumpASTBetweenEachPassIfNeeded(program, "AST after parsing"))
106         dumpASTAfterParsingIfNeeded(program);
107
108     NameResolver nameResolver(program.nameContext());
109     RUN_PASS(resolveNamesInTypes, program, nameResolver);
110     RUN_PASS(checkRecursiveTypes, program);
111     RUN_PASS(synthesizeStructureAccessors, program);
112     RUN_PASS(synthesizeEnumerationFunctions, program);
113     RUN_PASS(synthesizeArrayOperatorLength, program);
114     RUN_PASS(synthesizeConstructors, program);
115     RUN_PASS(resolveNamesInFunctions, program, nameResolver);
116     RUN_PASS(checkDuplicateFunctions, program);
117
118     RUN_PASS(check, program);
119
120     checkLiteralTypes(program);
121     resolveProperties(program);
122     findHighZombies(program);
123     RUN_PASS(checkStatementBehavior, program);
124     RUN_PASS(checkRecursion, program);
125     RUN_PASS(checkFunctionStages, program);
126
127     dumpASTAtEndIfNeeded(program);
128
129     return program;
130 }
131
132 Optional<RenderPrepareResult> prepare(String& whlslSource, RenderPipelineDescriptor& renderPipelineDescriptor)
133 {
134     auto program = prepareShared(whlslSource);
135     if (!program)
136         return WTF::nullopt;
137     auto matchedSemantics = matchSemantics(*program, renderPipelineDescriptor);
138     if (!matchedSemantics)
139         return WTF::nullopt;
140
141     auto generatedCode = Metal::generateMetalCode(*program, WTFMove(*matchedSemantics), renderPipelineDescriptor.layout);
142
143     RenderPrepareResult result;
144     result.metalSource = WTFMove(generatedCode.metalSource);
145     result.mangledVertexEntryPointName = WTFMove(generatedCode.mangledVertexEntryPointName);
146     result.mangledFragmentEntryPointName = WTFMove(generatedCode.mangledFragmentEntryPointName);
147     return result;
148 }
149
150 Optional<ComputePrepareResult> prepare(String& whlslSource, ComputePipelineDescriptor& computePipelineDescriptor)
151 {
152     auto program = prepareShared(whlslSource);
153     if (!program)
154         return WTF::nullopt;
155     auto matchedSemantics = matchSemantics(*program, computePipelineDescriptor);
156     if (!matchedSemantics)
157         return WTF::nullopt;
158
159     auto generatedCode = Metal::generateMetalCode(*program, WTFMove(*matchedSemantics), computePipelineDescriptor.layout);
160
161     ComputePrepareResult result;
162     result.metalSource = WTFMove(generatedCode.metalSource);
163     result.mangledEntryPointName = WTFMove(generatedCode.mangledEntryPointName);
164     return result;
165 }
166
167 } // namespace WHLSL
168
169 } // namespace WebCore
170
171 #endif // ENABLE(WEBGPU)