WebKit Bugzilla
Attachment 372418 Details for
Bug 198876
: [WHLSL] Support matrices
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for landing
c-backup.diff (text/plain), 32.87 KB, created by
Saam Barati
on 2019-06-18 18:53:49 PDT
(
hide
)
Description:
patch for landing
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-06-18 18:53:49 PDT
Size:
32.87 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 246578) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,48 @@ >+2019-06-18 Saam Barati <sbarati@apple.com> >+ >+ [WHLSL] Support matrices >+ https://bugs.webkit.org/show_bug.cgi?id=198876 >+ <rdar://problem/51768882> >+ >+ Reviewed by Dean Jackson and Myles Maxfield. >+ >+ This patch adds in support for matrices to WHLSL. Most matrix related code >+ is defined by the standard library. This patch just needed to add support >+ for the native functions operator[] and operator[]= on matrix types. The only >+ native functions that are named operator[] and operator[]= are for matrix >+ operations, so we strongly assume when generating code for native operator[] and >+ operator[]= that we're dealing with matrix types. >+ >+ operator[]= ignores the write if the index is out of bounds. operator[] >+ returns a zeroed vector if the index is out of bounds. >+ >+ This patch also incorporates two bug fixes: >+ 1. This patch takes Robin's patch in https://bugs.webkit.org/show_bug.cgi?id=198313 to ensure >+ we don't have pointers to values in a hash map. This was needed in this patch >+ otherwise we'd crash parsing the standard library. >+ >+ 2. This patch fixes how we handle "break" in metal codegen. When I first >+ implemented break, I strongly assumed we were in a loop. However, break >+ can be either from a loop or from switch. This patch teaches the metal code >+ generator to track which context we're in and to emit code accordingly. >+ >+ Tests: webgpu/whlsl-matrix-2.html >+ webgpu/whlsl-matrix.html >+ >+ * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp: >+ (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit): >+ (WebCore::WHLSL::Metal::FunctionDefinitionWriter::emitLoop): >+ * Modules/webgpu/WHLSL/Metal/WHLSLMetalCodeGenerator.cpp: >+ (WebCore::WHLSL::Metal::generateMetalCodeShared): >+ * Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp: >+ (WebCore::WHLSL::Metal::writeNativeFunction): >+ * Modules/webgpu/WHLSL/WHLSLChecker.cpp: >+ (WebCore::WHLSL::Checker::assignTypes): >+ (WebCore::WHLSL::Checker::getInfo): >+ (WebCore::WHLSL::Checker::assignType): >+ (WebCore::WHLSL::Checker::forwardType): >+ * Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt: >+ > 2019-06-18 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] JSLock should be WebThread aware >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (revision 246549) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (working copy) >@@ -507,7 +507,7 @@ private: > > void finishVisiting(AST::PropertyAccessExpression&, ResolvingType* additionalArgumentType = nullptr); > >- HashMap<AST::Expression*, ResolvingType> m_typeMap; >+ HashMap<AST::Expression*, std::unique_ptr<ResolvingType>> m_typeMap; > HashMap<AST::Expression*, AST::TypeAnnotation> m_typeAnnotations; > HashSet<String> m_vertexEntryPoints; > HashSet<String> m_fragmentEntryPoints; >@@ -537,7 +537,7 @@ void Checker::visit(Program& program) > bool Checker::assignTypes() > { > for (auto& keyValuePair : m_typeMap) { >- auto success = keyValuePair.value.visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { >+ auto success = keyValuePair.value->visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& unnamedType) -> bool { > keyValuePair.key->setType(unnamedType->clone()); > return true; > }, [&](RefPtr<ResolvableTypeReference>& resolvableTypeReference) -> bool { >@@ -780,7 +780,7 @@ auto Checker::getInfo(AST::Expression& e > setError(); > return WTF::nullopt; > } >- return {{ typeIterator->value, typeAnnotationIterator->value }}; >+ return {{ *typeIterator->value, typeAnnotationIterator->value }}; > } > > void Checker::visit(AST::VariableDeclaration& variableDeclaration) >@@ -802,7 +802,7 @@ void Checker::visit(AST::VariableDeclara > > void Checker::assignType(AST::Expression& expression, UniqueRef<AST::UnnamedType>&& unnamedType, AST::TypeAnnotation typeAnnotation = AST::RightValue()) > { >- auto addResult = m_typeMap.add(&expression, WTFMove(unnamedType)); >+ auto addResult = m_typeMap.add(&expression, std::make_unique<ResolvingType>(WTFMove(unnamedType))); > ASSERT_UNUSED(addResult, addResult.isNewEntry); > auto typeAnnotationAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); > ASSERT_UNUSED(typeAnnotationAddResult, typeAnnotationAddResult.isNewEntry); >@@ -810,7 +810,7 @@ void Checker::assignType(AST::Expression > > void Checker::assignType(AST::Expression& expression, RefPtr<ResolvableTypeReference>&& resolvableTypeReference, AST::TypeAnnotation typeAnnotation = AST::RightValue()) > { >- auto addResult = m_typeMap.add(&expression, WTFMove(resolvableTypeReference)); >+ auto addResult = m_typeMap.add(&expression, std::make_unique<ResolvingType>(WTFMove(resolvableTypeReference))); > ASSERT_UNUSED(addResult, addResult.isNewEntry); > auto typeAnnotationAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); > ASSERT_UNUSED(typeAnnotationAddResult, typeAnnotationAddResult.isNewEntry); >@@ -819,10 +819,10 @@ void Checker::assignType(AST::Expression > void Checker::forwardType(AST::Expression& expression, ResolvingType& resolvingType, AST::TypeAnnotation typeAnnotation = AST::RightValue()) > { > resolvingType.visit(WTF::makeVisitor([&](UniqueRef<AST::UnnamedType>& result) { >- auto addResult = m_typeMap.add(&expression, result->clone()); >+ auto addResult = m_typeMap.add(&expression, std::make_unique<ResolvingType>(result->clone())); > ASSERT_UNUSED(addResult, addResult.isNewEntry); > }, [&](RefPtr<ResolvableTypeReference>& result) { >- auto addResult = m_typeMap.add(&expression, result.copyRef()); >+ auto addResult = m_typeMap.add(&expression, std::make_unique<ResolvingType>(result.copyRef())); > ASSERT_UNUSED(addResult, addResult.isNewEntry); > })); > auto typeAnnotationAddResult = m_typeAnnotations.add(&expression, WTFMove(typeAnnotation)); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (revision 246549) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (working copy) >@@ -625,4 +625,227 @@ operator float4(float x, float y, float > return result; > } > >+native float3 operator[](float2x3, uint); >+native float2x3 operator[]=(float2x3, uint, float3); >+float operator[](float3 v, uint index) { >+ switch (index) { >+ case 0: >+ return v.x; >+ case 1: >+ return v.y; >+ case 2: >+ return v.z; >+ default: >+ break; >+ } >+ return 0.0; >+} >+float3 operator[]=(float3 v, uint index, float a) { >+ switch (index) { >+ case 0: >+ v.x = a; >+ break; >+ case 1: >+ v.y = a; >+ break; >+ case 2: >+ v.z = a; >+ break; >+ default: >+ break; >+ } >+ return v; >+} >+float2x3 operator+(float2x3 a, float2x3 b) { >+ float2x3 result; >+ result[0][0] = a[0][0] + b[0][0]; >+ result[0][1] = a[0][1] + b[0][1]; >+ result[0][2] = a[0][2] + b[0][2]; >+ result[1][0] = a[1][0] + b[1][0]; >+ result[1][1] = a[1][1] + b[1][1]; >+ result[1][2] = a[1][2] + b[1][2]; >+ return result; >+} >+float2x3 operator*(float2x3 a, float b) { >+ float2x3 result; >+ result[0][0] = a[0][0] * b; >+ result[0][1] = a[0][1] * b; >+ result[0][2] = a[0][2] * b; >+ result[1][0] = a[1][0] * b; >+ result[1][1] = a[1][1] * b; >+ result[1][2] = a[1][2] * b; >+ return result; >+} >+float2x3 operator+(float2x3 a, float b) { >+ float2x3 result; >+ result[0][0] = a[0][0] + b; >+ result[0][1] = a[0][1] + b; >+ result[0][2] = a[0][2] + b; >+ result[1][0] = a[1][0] + b; >+ result[1][1] = a[1][1] + b; >+ result[1][2] = a[1][2] + b; >+ return result; >+} >+float2x3 operator-(float2x3 a, float b) { >+ float2x3 result; >+ result[0][0] = a[0][0] - b; >+ result[0][1] = a[0][1] - b; >+ result[0][2] = a[0][2] - b; >+ result[1][0] = a[1][0] - b; >+ result[1][1] = a[1][1] - b; >+ result[1][2] = a[1][2] - b; >+ return result; >+} >+ >+typedef float4x4 = matrix<float, 4, 4>; >+native float4 operator[](float4x4, uint); >+native float4x4 operator[]=(float4x4, uint, float4); >+ >+float operator[](float4 v, uint index) { >+ switch (index) { >+ case 0: >+ return v.x; >+ case 1: >+ return v.y; >+ case 2: >+ return v.z; >+ case 3: >+ return v.w; >+ default: >+ break; >+ } >+ float result; >+ return result; >+} >+ >+float4 operator[]=(float4 v, uint index, float a) { >+ switch (index) { >+ case 0: >+ v.x = a; >+ break; >+ case 1: >+ v.y = a; >+ break; >+ case 2: >+ v.z = a; >+ break; >+ case 3: >+ v.w = a; >+ break; >+ default: >+ break; >+ } >+ return v; >+} >+ >+float4 mul(float4x4 x, float4 y) { >+ float4 result; >+ result[0] = 0; >+ result[0] = result[0] + x[0][0] * y[0]; >+ result[0] = result[0] + x[0][1] * y[1]; >+ result[0] = result[0] + x[0][2] * y[2]; >+ result[0] = result[0] + x[0][3] * y[3]; >+ result[1] = 0; >+ result[1] = result[1] + x[1][0] * y[0]; >+ result[1] = result[1] + x[1][1] * y[1]; >+ result[1] = result[1] + x[1][2] * y[2]; >+ result[1] = result[1] + x[1][3] * y[3]; >+ result[2] = 0; >+ result[2] = result[2] + x[2][0] * y[0]; >+ result[2] = result[2] + x[2][1] * y[1]; >+ result[2] = result[2] + x[2][2] * y[2]; >+ result[2] = result[2] + x[2][3] * y[3]; >+ result[3] = 0; >+ result[3] = result[3] + x[3][0] * y[0]; >+ result[3] = result[3] + x[3][1] * y[1]; >+ result[3] = result[3] + x[3][2] * y[2]; >+ result[3] = result[3] + x[3][3] * y[3]; >+ return result; >+} >+ >+float4x4 mul(float4x4 x, float4x4 y) { >+ float4x4 result; >+ result[0][0] = 0; >+ result[0][0] = result[0][0] + x[0][0] * y[0][0]; >+ result[0][0] = result[0][0] + x[0][1] * y[1][0]; >+ result[0][0] = result[0][0] + x[0][2] * y[2][0]; >+ result[0][0] = result[0][0] + x[0][3] * y[3][0]; >+ result[0][1] = 0; >+ result[0][1] = result[0][1] + x[0][0] * y[0][1]; >+ result[0][1] = result[0][1] + x[0][1] * y[1][1]; >+ result[0][1] = result[0][1] + x[0][2] * y[2][1]; >+ result[0][1] = result[0][1] + x[0][3] * y[3][1]; >+ result[0][2] = 0; >+ result[0][2] = result[0][2] + x[0][0] * y[0][2]; >+ result[0][2] = result[0][2] + x[0][1] * y[1][2]; >+ result[0][2] = result[0][2] + x[0][2] * y[2][2]; >+ result[0][2] = result[0][2] + x[0][3] * y[3][2]; >+ result[0][3] = 0; >+ result[0][3] = result[0][3] + x[0][0] * y[0][3]; >+ result[0][3] = result[0][3] + x[0][1] * y[1][3]; >+ result[0][3] = result[0][3] + x[0][2] * y[2][3]; >+ result[0][3] = result[0][3] + x[0][3] * y[3][3]; >+ result[1][0] = 0; >+ result[1][0] = result[1][0] + x[1][0] * y[0][0]; >+ result[1][0] = result[1][0] + x[1][1] * y[1][0]; >+ result[1][0] = result[1][0] + x[1][2] * y[2][0]; >+ result[1][0] = result[1][0] + x[1][3] * y[3][0]; >+ result[1][1] = 0; >+ result[1][1] = result[1][1] + x[1][0] * y[0][1]; >+ result[1][1] = result[1][1] + x[1][1] * y[1][1]; >+ result[1][1] = result[1][1] + x[1][2] * y[2][1]; >+ result[1][1] = result[1][1] + x[1][3] * y[3][1]; >+ result[1][2] = 0; >+ result[1][2] = result[1][2] + x[1][0] * y[0][2]; >+ result[1][2] = result[1][2] + x[1][1] * y[1][2]; >+ result[1][2] = result[1][2] + x[1][2] * y[2][2]; >+ result[1][2] = result[1][2] + x[1][3] * y[3][2]; >+ result[1][3] = 0; >+ result[1][3] = result[1][3] + x[1][0] * y[0][3]; >+ result[1][3] = result[1][3] + x[1][1] * y[1][3]; >+ result[1][3] = result[1][3] + x[1][2] * y[2][3]; >+ result[1][3] = result[1][3] + x[1][3] * y[3][3]; >+ result[2][0] = 0; >+ result[2][0] = result[2][0] + x[2][0] * y[0][0]; >+ result[2][0] = result[2][0] + x[2][1] * y[1][0]; >+ result[2][0] = result[2][0] + x[2][2] * y[2][0]; >+ result[2][0] = result[2][0] + x[2][3] * y[3][0]; >+ result[2][1] = 0; >+ result[2][1] = result[2][1] + x[2][0] * y[0][1]; >+ result[2][1] = result[2][1] + x[2][1] * y[1][1]; >+ result[2][1] = result[2][1] + x[2][2] * y[2][1]; >+ result[2][1] = result[2][1] + x[2][3] * y[3][1]; >+ result[2][2] = 0; >+ result[2][2] = result[2][2] + x[2][0] * y[0][2]; >+ result[2][2] = result[2][2] + x[2][1] * y[1][2]; >+ result[2][2] = result[2][2] + x[2][2] * y[2][2]; >+ result[2][2] = result[2][2] + x[2][3] * y[3][2]; >+ result[2][3] = 0; >+ result[2][3] = result[2][3] + x[2][0] * y[0][3]; >+ result[2][3] = result[2][3] + x[2][1] * y[1][3]; >+ result[2][3] = result[2][3] + x[2][2] * y[2][3]; >+ result[2][3] = result[2][3] + x[2][3] * y[3][3]; >+ result[3][0] = 0; >+ result[3][0] = result[3][0] + x[3][0] * y[0][0]; >+ result[3][0] = result[3][0] + x[3][1] * y[1][0]; >+ result[3][0] = result[3][0] + x[3][2] * y[2][0]; >+ result[3][0] = result[3][0] + x[3][3] * y[3][0]; >+ result[3][1] = 0; >+ result[3][1] = result[3][1] + x[3][0] * y[0][1]; >+ result[3][1] = result[3][1] + x[3][1] * y[1][1]; >+ result[3][1] = result[3][1] + x[3][2] * y[2][1]; >+ result[3][1] = result[3][1] + x[3][3] * y[3][1]; >+ result[3][2] = 0; >+ result[3][2] = result[3][2] + x[3][0] * y[0][2]; >+ result[3][2] = result[3][2] + x[3][1] * y[1][2]; >+ result[3][2] = result[3][2] + x[3][2] * y[2][2]; >+ result[3][2] = result[3][2] + x[3][3] * y[3][2]; >+ result[3][3] = 0; >+ result[3][3] = result[3][3] + x[3][0] * y[0][3]; >+ result[3][3] = result[3][3] + x[3][1] * y[1][3]; >+ result[3][3] = result[3][3] + x[3][2] * y[2][3]; >+ result[3][3] = result[3][3] + x[3][3] * y[3][3]; >+ return result; >+} >+ > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=192890 Insert the rest of the standard library once the parser is fast enough >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (revision 246549) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (working copy) >@@ -191,6 +191,13 @@ protected: > return m_stack.takeLast().leftValue; > } > >+ enum class BreakContext { >+ Loop, >+ Switch >+ }; >+ >+ Optional<BreakContext> m_currentBreakContext; >+ > Intrinsics& m_intrinsics; > TypeNamer& m_typeNamer; > HashMap<AST::FunctionDeclaration*, String>& m_functionMapping; >@@ -271,9 +278,17 @@ void FunctionDefinitionWriter::visit(AST > > void FunctionDefinitionWriter::visit(AST::Break&) > { >- ASSERT(m_breakOutOfCurrentLoopEarlyVariable.length()); >- m_stringBuilder.append(makeString(m_breakOutOfCurrentLoopEarlyVariable, " = true;\n")); >- m_stringBuilder.append("break;\n"); >+ ASSERT(m_currentBreakContext); >+ switch (*m_currentBreakContext) { >+ case BreakContext::Switch: >+ m_stringBuilder.append("break;\n"); >+ break; >+ case BreakContext::Loop: >+ ASSERT(m_breakOutOfCurrentLoopEarlyVariable.length()); >+ m_stringBuilder.append(makeString(m_breakOutOfCurrentLoopEarlyVariable, " = true;\n")); >+ m_stringBuilder.append("break;\n"); >+ break; >+ } > } > > void FunctionDefinitionWriter::visit(AST::Continue&) >@@ -307,6 +322,7 @@ void FunctionDefinitionWriter::emitLoop( > } > > m_stringBuilder.append("do {\n"); >+ SetForScope<Optional<BreakContext>> breakContext(m_currentBreakContext, BreakContext::Loop); > checkErrorAndVisit(body); > m_stringBuilder.append("} while(false); \n"); > m_stringBuilder.append(makeString("if (", m_breakOutOfCurrentLoopEarlyVariable, ") break;\n")); >@@ -393,9 +409,9 @@ void FunctionDefinitionWriter::visit(AST > m_stringBuilder.append(makeString("case ", constantExpressionString(*switchCase.value()), ":\n")); > else > m_stringBuilder.append("default:\n"); >+ SetForScope<Optional<BreakContext>> breakContext(m_currentBreakContext, BreakContext::Switch); > checkErrorAndVisit(switchCase.block()); > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195812 Figure out whether we need to break or fallthrough. >- notImplemented(); > } > > void FunctionDefinitionWriter::visit(AST::Trap&) >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLMetalCodeGenerator.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLMetalCodeGenerator.cpp (revision 246549) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLMetalCodeGenerator.cpp (working copy) >@@ -30,6 +30,7 @@ > > #include "WHLSLFunctionWriter.h" > #include "WHLSLTypeNamer.h" >+#include <wtf/DataLog.h> > #include <wtf/text/StringBuilder.h> > > namespace WebCore { >@@ -38,6 +39,8 @@ namespace WHLSL { > > namespace Metal { > >+static constexpr bool dumpMetalCode = false; >+ > static String generateMetalCodeShared(String&& metalTypes, String&& metalFunctions) > { > StringBuilder stringBuilder; >@@ -53,6 +56,12 @@ static String generateMetalCodeShared(St > > stringBuilder.append(WTFMove(metalTypes)); > stringBuilder.append(WTFMove(metalFunctions)); >+ >+ if (dumpMetalCode) { >+ dataLogLn("Generated Metal code: "); >+ dataLogLn(stringBuilder.toString()); >+ } >+ > return stringBuilder.toString(); > } > >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp (revision 246549) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp (working copy) >@@ -225,6 +225,39 @@ String writeNativeFunction(AST::NativeFu > return stringBuilder.toString(); > } > >+ auto numberOfMatrixRows = [&] { >+ auto& typeReference = downcast<AST::TypeReference>(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto& matrixType = downcast<AST::NativeTypeDeclaration>(downcast<AST::TypeReference>(downcast<AST::TypeDefinition>(typeReference.resolvedType()).type()).resolvedType()); >+ ASSERT(matrixType.name() == "matrix"); >+ ASSERT(matrixType.typeArguments().size() == 3); >+ return String::number(WTF::get<AST::ConstantExpression>(matrixType.typeArguments()[1]).integerLiteral().value()); >+ }; >+ >+ if (nativeFunctionDeclaration.name() == "operator[]") { >+ ASSERT(nativeFunctionDeclaration.parameters().size() == 2); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); >+ auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); >+ stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " m, ", metalParameter2Name, " i) {\n")); >+ stringBuilder.append(makeString(" if (i < ", numberOfMatrixRows(), ") return m[i];\n")); >+ stringBuilder.append(makeString(" return ", metalReturnName, "(0);\n")); >+ stringBuilder.append("}\n"); >+ return stringBuilder.toString(); >+ } >+ >+ if (nativeFunctionDeclaration.name() == "operator[]=") { >+ ASSERT(nativeFunctionDeclaration.parameters().size() == 3); >+ auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); >+ auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); >+ auto metalParameter3Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[2]->type()); >+ auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); >+ stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " m, ", metalParameter2Name, " i, ", metalParameter3Name, " v) {\n")); >+ stringBuilder.append(makeString(" if (i < ", numberOfMatrixRows(), ") m[i] = v;\n")); >+ stringBuilder.append(" return m;\n"); >+ stringBuilder.append("}\n"); >+ return stringBuilder.toString(); >+ } >+ > if (nativeFunctionDeclaration.isOperator()) { > if (nativeFunctionDeclaration.parameters().size() == 1) { > auto operatorName = nativeFunctionDeclaration.name().substring("operator"_str.length()); >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 246550) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,16 @@ >+2019-06-18 Saam Barati <sbarati@apple.com> >+ >+ [WHLSL] Support matrices >+ https://bugs.webkit.org/show_bug.cgi?id=198876 >+ <rdar://problem/51768882> >+ >+ Reviewed by Dean Jackson and Myles Maxfield. >+ >+ * webgpu/whlsl-matrix-2-expected.txt: Added. >+ * webgpu/whlsl-matrix-2.html: Added. >+ * webgpu/whlsl-matrix-expected.txt: Added. >+ * webgpu/whlsl-matrix.html: Added. >+ > 2019-06-18 Saam Barati <sbarati@apple.com> > > [WHLSL] Do not generate duplicate constructors/copy constructors in synthesizeConstructors >Index: LayoutTests/webgpu/whlsl-matrix-2-expected.txt >=================================================================== >--- LayoutTests/webgpu/whlsl-matrix-2-expected.txt (nonexistent) >+++ LayoutTests/webgpu/whlsl-matrix-2-expected.txt (working copy) >@@ -0,0 +1,12 @@ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS resultsFloat32Array[0] is 2 >+PASS resultsFloat32Array[1] is 4 >+PASS resultsFloat32Array[2] is 6 >+PASS resultsFloat32Array[3] is 8 >+PASS resultsFloat32Array[4] is 5 >+PASS resultsFloat32Array[5] is 6 >+PASS resultsFloat32Array[6] is 7 >+PASS resultsFloat32Array[7] is 8 >+ >Index: LayoutTests/webgpu/whlsl-matrix-2.html >=================================================================== >--- LayoutTests/webgpu/whlsl-matrix-2.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-matrix-2.html (working copy) >@@ -0,0 +1,152 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+const shaderSource = ` >+bool allEqual(float4x4 mat, float value) >+{ >+ for (uint i = 0; i < 4; i = i + 1) { >+ for (uint j = 0; j < 4; j = j + 1) { >+ if (mat[i][j] != value) >+ return false; >+ } >+ } >+ return true; >+} >+ >+bool fill(thread float4x4* mat, float value) >+{ >+ float4x4 result; >+ for (uint i = 0; i < 4; i = i + 1) { >+ result[i] = float4(value, value, value, value); >+ } >+ *mat = result; >+ return true; >+} >+ >+bool fill(thread float4* vec, float value) >+{ >+ float4 result; >+ for (uint i = 0; i < 4; i = i + 1) { >+ result[i] = value; >+ } >+ *vec = result; >+ return true; >+} >+ >+bool allEqual(float4 vec, float value) >+{ >+ for (uint i = 0; i < 4; i = i + 1) { >+ if (vec[i] != value) >+ return false; >+ } >+ return true; >+} >+ >+[numthreads(1, 1, 1)] >+compute void computeShader(device float[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) { >+ float4x4 mat; >+ fill(&mat, 1); >+ if (!allEqual(mat, 1)) >+ return; >+ >+ float4 vec; >+ fill(&vec, 1); >+ if (!allEqual(vec, 1)) >+ return; >+ >+ float4 vec2 = mul(mat, vec); >+ if (!allEqual(vec2, 4)) >+ return; >+ >+ float4x4 mat2 = mul(mat, mat); >+ if (!allEqual(mat2, 4)) >+ return; >+ >+ mat2 = mul(mat2, mat2); >+ if (!allEqual(mat2, 64)) >+ return; >+ >+ buffer[uint(threadID.x)] = buffer[uint(threadID.x)] * 2.0; >+} >+`; >+let resultsFloat32Array; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const computeStage = {module: shaderModule, entryPoint: "computeShader"}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const computePipelineDescriptor = {computeStage, layout: pipelineLayout}; >+ const computePipeline = device.createComputePipeline(computePipelineDescriptor); >+ >+ const size = Float32Array.BYTES_PER_ELEMENT * 8; >+ >+ const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC}; >+ const buffer = device.createBuffer(bufferDescriptor); >+ const bufferArrayBuffer = await buffer.mapWriteAsync(); >+ const bufferFloat32Array = new Float32Array(bufferArrayBuffer); >+ bufferFloat32Array[0] = 1; >+ bufferFloat32Array[1] = 2; >+ bufferFloat32Array[2] = 3; >+ bufferFloat32Array[3] = 4; >+ bufferFloat32Array[4] = 5; >+ bufferFloat32Array[5] = 6; >+ bufferFloat32Array[6] = 7; >+ bufferFloat32Array[7] = 8; >+ buffer.unmap(); >+ >+ const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ}; >+ const resultsBuffer = device.createBuffer(resultsBufferDescriptor); >+ >+ const bufferBinding = {buffer: resultsBuffer, size}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size); >+ const computePassEncoder = commandEncoder.beginComputePass(); >+ computePassEncoder.setPipeline(computePipeline); >+ computePassEncoder.setBindGroup(0, bindGroup); >+ computePassEncoder.dispatch(4, 1, 1); >+ computePassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ const resultsArrayBuffer = await resultsBuffer.mapReadAsync(); >+ resultsFloat32Array = new Float32Array(resultsArrayBuffer); >+ shouldBe("resultsFloat32Array[0]", "2"); >+ shouldBe("resultsFloat32Array[1]", "4"); >+ shouldBe("resultsFloat32Array[2]", "6"); >+ shouldBe("resultsFloat32Array[3]", "8"); >+ shouldBe("resultsFloat32Array[4]", "5"); >+ shouldBe("resultsFloat32Array[5]", "6"); >+ shouldBe("resultsFloat32Array[6]", "7"); >+ shouldBe("resultsFloat32Array[7]", "8"); >+ resultsBuffer.unmap(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", function() { >+ start().then(function() { >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ }, function() { >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ }); >+}); >+</script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-matrix-expected.txt >=================================================================== >--- LayoutTests/webgpu/whlsl-matrix-expected.txt (nonexistent) >+++ LayoutTests/webgpu/whlsl-matrix-expected.txt (working copy) >@@ -0,0 +1,12 @@ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS resultsFloat32Array[0] is 2 >+PASS resultsFloat32Array[1] is 4 >+PASS resultsFloat32Array[2] is 6 >+PASS resultsFloat32Array[3] is 8 >+PASS resultsFloat32Array[4] is 5 >+PASS resultsFloat32Array[5] is 6 >+PASS resultsFloat32Array[6] is 7 >+PASS resultsFloat32Array[7] is 8 >+ >Index: LayoutTests/webgpu/whlsl-matrix.html >=================================================================== >--- LayoutTests/webgpu/whlsl-matrix.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-matrix.html (working copy) >@@ -0,0 +1,164 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+const shaderSource = ` >+bool allEqual(float2x3 mat, float value) >+{ >+ for (uint i = 0; i < 2; i = i + 1) { >+ for (uint j = 0; j < 3; j = j + 1) { >+ if (mat[i][j] != value) >+ return false; >+ } >+ } >+ return true; >+} >+ >+[numthreads(1, 1, 1)] >+compute void computeShader(device float[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) { >+ float2x3 foo; >+ if (!allEqual(foo, 0)) >+ return; >+ >+ foo = foo + 1.0; >+ if (!allEqual(foo, 1)) >+ return; >+ >+ foo = foo * 8.5; >+ if (!allEqual(foo, 8.5)) >+ return; >+ >+ foo = foo - 7.5; >+ if (!allEqual(foo, 1)) >+ return; >+ >+ foo = foo + 1.0; >+ if (!allEqual(foo, 2)) >+ return; >+ >+ foo = foo + foo; >+ if (!allEqual(foo, 4)) >+ return; >+ >+ foo = foo + foo; >+ if (!allEqual(foo, 8)) >+ return; >+ >+ float3 fourtyTwo; >+ fourtyTwo.x = 42; >+ fourtyTwo.y = 42; >+ fourtyTwo.z = 42; >+ >+ foo[0] = fourtyTwo; >+ foo[1] = fourtyTwo; >+ if (!allEqual(foo, 42)) >+ return; >+ >+ foo[1337] = fourtyTwo; >+ if (!allEqual(foo, 42)) >+ return; >+ >+ foo[1000000] = fourtyTwo; >+ if (!allEqual(foo, 42)) >+ return; >+ >+ fourtyTwo[1337] = 50; >+ foo[1] = fourtyTwo; >+ if (!allEqual(foo, 42)) >+ return; >+ >+ fourtyTwo[1000000] = 50; >+ foo[1] = fourtyTwo; >+ if (!allEqual(foo, 42)) >+ return; >+ >+ float3 shouldBeZero = foo[100000]; >+ if (shouldBeZero.x != 0 || shouldBeZero.y != 0 || shouldBeZero.z != 0) >+ return; >+ >+ if (fourtyTwo[10000000] != 0) >+ return; >+ >+ buffer[uint(threadID.x)] = buffer[uint(threadID.x)] * 2.0; >+} >+`; >+let resultsFloat32Array; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const computeStage = {module: shaderModule, entryPoint: "computeShader"}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const computePipelineDescriptor = {computeStage, layout: pipelineLayout}; >+ const computePipeline = device.createComputePipeline(computePipelineDescriptor); >+ >+ const size = Float32Array.BYTES_PER_ELEMENT * 8; >+ >+ const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC}; >+ const buffer = device.createBuffer(bufferDescriptor); >+ const bufferArrayBuffer = await buffer.mapWriteAsync(); >+ const bufferFloat32Array = new Float32Array(bufferArrayBuffer); >+ bufferFloat32Array[0] = 1; >+ bufferFloat32Array[1] = 2; >+ bufferFloat32Array[2] = 3; >+ bufferFloat32Array[3] = 4; >+ bufferFloat32Array[4] = 5; >+ bufferFloat32Array[5] = 6; >+ bufferFloat32Array[6] = 7; >+ bufferFloat32Array[7] = 8; >+ buffer.unmap(); >+ >+ const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ}; >+ const resultsBuffer = device.createBuffer(resultsBufferDescriptor); >+ >+ const bufferBinding = {buffer: resultsBuffer, size}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size); >+ const computePassEncoder = commandEncoder.beginComputePass(); >+ computePassEncoder.setPipeline(computePipeline); >+ computePassEncoder.setBindGroup(0, bindGroup); >+ computePassEncoder.dispatch(4, 1, 1); >+ computePassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ const resultsArrayBuffer = await resultsBuffer.mapReadAsync(); >+ resultsFloat32Array = new Float32Array(resultsArrayBuffer); >+ shouldBe("resultsFloat32Array[0]", "2"); >+ shouldBe("resultsFloat32Array[1]", "4"); >+ shouldBe("resultsFloat32Array[2]", "6"); >+ shouldBe("resultsFloat32Array[3]", "8"); >+ shouldBe("resultsFloat32Array[4]", "5"); >+ shouldBe("resultsFloat32Array[5]", "6"); >+ shouldBe("resultsFloat32Array[6]", "7"); >+ shouldBe("resultsFloat32Array[7]", "8"); >+ resultsBuffer.unmap(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", function() { >+ start().then(function() { >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ }, function() { >+ if (window.testRunner) >+ testRunner.notifyDone(); >+ }); >+}); >+</script> >+<script src="../resources/js-test-post.js"></script> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198876
:
372404
|
372409
| 372418