WebKit Bugzilla
Attachment 372013 Details for
Bug 198600
: [WHLSL] Implement out-of-bounds and nullptr behavior
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
a-backup.diff (text/plain), 182.92 KB, created by
Saam Barati
on 2019-06-12 19:04:42 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-06-12 19:04:42 PDT
Size:
182.92 KB
patch
obsolete
>Index: Source/WebCore/Sources.txt >=================================================================== >--- Source/WebCore/Sources.txt (revision 246326) >+++ Source/WebCore/Sources.txt (working copy) >@@ -306,6 +306,7 @@ Modules/websockets/WorkerThreadableWebSo > > Modules/webgpu/GPUCanvasContext.cpp > Modules/webgpu/NavigatorGPU.cpp >+Modules/webgpu/WHLSL/WHLSLComputeDimensions.cpp > Modules/webgpu/WHLSL/WHLSLASTDumper.cpp > Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.cpp > Modules/webgpu/WHLSL/WHLSLInferTypes.cpp >Index: Source/WebCore/SourcesCocoa.txt >=================================================================== >--- Source/WebCore/SourcesCocoa.txt (revision 246326) >+++ Source/WebCore/SourcesCocoa.txt (working copy) >@@ -326,6 +326,7 @@ platform/graphics/gpu/cocoa/GPUCommandBu > platform/graphics/gpu/cocoa/GPUComputePassEncoderMetal.mm > platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm > platform/graphics/gpu/cocoa/GPUDeviceMetal.mm >+platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.cpp > platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm > platform/graphics/gpu/cocoa/GPUQueueMetal.mm > platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm >Index: Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp (working copy) >@@ -111,7 +111,7 @@ Optional<GPUBindGroupDescriptor> WebGPUB > if (!buffer) > return WTF::nullopt; > >- if (!validateBufferBindingType(buffer, layoutBinding, functionName)) >+ if (!validateBufferBindingType(buffer, layoutBinding.externalBinding, functionName)) > return WTF::nullopt; > > return static_cast<GPUBindingResource>(GPUBufferBinding { makeRef(*buffer), bufferBinding.offset, bufferBinding.size }); >@@ -119,7 +119,7 @@ Optional<GPUBindGroupDescriptor> WebGPUB > > auto bindingResource = WTF::visit(bindingResourceVisitor, binding.resource); > if (!bindingResource) { >- LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.binding); >+ LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.externalBinding.binding); > return WTF::nullopt; > } > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (working copy) >@@ -36,6 +36,7 @@ > #include "WHLSLDereferenceExpression.h" > #include "WHLSLDoWhileLoop.h" > #include "WHLSLDotExpression.h" >+#include "WHLSLEntryPointType.h" > #include "WHLSLForLoop.h" > #include "WHLSLGatherEntryPointItems.h" > #include "WHLSLIfStatement.h" >@@ -116,29 +117,29 @@ public: > } > }; > >-static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(AST::CallExpression& callExpression, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics) >+static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(Lexer::Token origin, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics) > { > const bool isOperator = true; >- auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(callExpression.origin()), firstArgument.addressSpace(), firstArgument.elementType().clone()); >+ auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(origin), firstArgument.addressSpace(), firstArgument.elementType().clone()); > AST::VariableDeclarations parameters; >- parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); >- parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType())), String(), WTF::nullopt, WTF::nullopt)); >- return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.uintType())), String(), WTF::nullopt, WTF::nullopt)); >+ return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > >-static AST::NativeFunctionDeclaration resolveWithOperatorLength(AST::CallExpression& callExpression, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics) >+static AST::NativeFunctionDeclaration resolveWithOperatorLength(Lexer::Token origin, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics) > { > const bool isOperator = true; >- auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType()); >+ auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.uintType()); > AST::VariableDeclarations parameters; >- parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); >- return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator.length", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt)); >+ return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator.length", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > >-static AST::NativeFunctionDeclaration resolveWithReferenceComparator(AST::CallExpression& callExpression, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics) >+static AST::NativeFunctionDeclaration resolveWithReferenceComparator(Lexer::Token origin, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics) > { > const bool isOperator = true; >- auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.boolType()); >+ auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.boolType()); > auto argumentType = firstArgument.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> UniqueRef<AST::UnnamedType> { > return unnamedType->clone(); > }, [&](RefPtr<ResolvableTypeReference>&) -> UniqueRef<AST::UnnamedType> { >@@ -148,13 +149,13 @@ static AST::NativeFunctionDeclaration re > // We encountered "null == null". > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198162 This can probably be generalized, using the "preferred type" infrastructure used by generic literals > ASSERT_NOT_REACHED(); >- return AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.intType()); >+ return AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.intType()); > })); > })); > AST::VariableDeclarations parameters; >- parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), argumentType->clone(), String(), WTF::nullopt, WTF::nullopt)); >- parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt)); >- return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), argumentType->clone(), String(), WTF::nullopt, WTF::nullopt)); >+ parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt)); >+ return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator)); > } > > enum class Acceptability { >@@ -163,9 +164,9 @@ enum class Acceptability { > No > }; > >-static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(AST::CallExpression& callExpression, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics) >+static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const String& name, Lexer::Token origin, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics) > { >- if (callExpression.name() == "operator&[]" && types.size() == 2) { >+ if (name == "operator&[]" && types.size() == 2) { > auto* firstArgumentArrayRef = types[0].get().visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::ArrayReferenceType* { > if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType))) > return &downcast<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)); >@@ -179,8 +180,8 @@ static Optional<AST::NativeFunctionDecla > return resolvableTypeReference->resolvableType().canResolve(intrinsics.uintType()); > })); > if (firstArgumentArrayRef && secondArgumentIsUint) >- return resolveWithOperatorAnderIndexer(callExpression, *firstArgumentArrayRef, intrinsics); >- } else if (callExpression.name() == "operator.length" && types.size() == 1) { >+ return resolveWithOperatorAnderIndexer(origin, *firstArgumentArrayRef, intrinsics); >+ } else if (name == "operator.length" && types.size() == 1) { > auto* firstArgumentReference = types[0].get().visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::UnnamedType* { > if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType))) > return &unnamedType; >@@ -189,8 +190,8 @@ static Optional<AST::NativeFunctionDecla > return nullptr; > })); > if (firstArgumentReference) >- return resolveWithOperatorLength(callExpression, *firstArgumentReference, intrinsics); >- } else if (callExpression.name() == "operator==" && types.size() == 2) { >+ return resolveWithOperatorLength(origin, *firstArgumentReference, intrinsics); >+ } else if (name == "operator==" && types.size() == 2) { > auto acceptability = [](ResolvingType& resolvingType) -> Acceptability { > return resolvingType.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> Acceptability { > return is<AST::ReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)) ? Acceptability::Yes : Acceptability::No; >@@ -209,7 +210,7 @@ static Optional<AST::NativeFunctionDecla > || (leftAcceptability == Acceptability::Yes && rightAcceptability == Acceptability::Maybe)) > success = true; > if (success) >- return resolveWithReferenceComparator(callExpression, types[0].get(), types[1].get(), intrinsics); >+ return resolveWithReferenceComparator(origin, types[0].get(), types[1].get(), intrinsics); > } > return WTF::nullopt; > } >@@ -354,7 +355,7 @@ static bool checkOperatorOverload(const > Vector<ResolvingType> argumentTypes; > Vector<std::reference_wrapper<ResolvingType>> argumentTypeReferences; > for (size_t i = 0; i < numExpectedParameters - 1; ++i) >- argumentTypes.append((*functionDefinition.parameters()[0]->type())->clone()); >+ argumentTypes.append((*functionDefinition.parameters()[i]->type())->clone()); > for (auto& argumentType : argumentTypes) > argumentTypeReferences.append(argumentType); > auto* overload = resolveFunctionOverload(*getterFuncs, argumentTypeReferences); >@@ -491,6 +492,8 @@ private: > void visit(AST::TernaryExpression&) override; > void visit(AST::CallExpression&) override; > >+ void finishVisiting(AST::PropertyAccessExpression&, ResolvingType* additionalArgumentType = nullptr); >+ > HashMap<AST::Expression*, ResolvingType> m_typeMap; > HashMap<AST::Expression*, AST::TypeAnnotation> m_typeAnnotations; > HashSet<String> m_vertexEntryPoints; >@@ -966,9 +969,32 @@ void Checker::visit(AST::MakeArrayRefere > assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *leftAddressSpace, leftValueType->clone())); > } > >-void Checker::visit(AST::DotExpression& dotExpression) >+static Optional<UniqueRef<AST::UnnamedType>> argumentTypeForAndOverload(AST::UnnamedType& baseType, AST::AddressSpace addressSpace) >+{ >+ auto& unifyNode = baseType.unifyNode(); >+ if (is<AST::NamedType>(unifyNode)) { >+ auto& namedType = downcast<AST::NamedType>(unifyNode); >+ return { makeUniqueRef<AST::PointerType>(Lexer::Token(namedType.origin()), addressSpace, AST::TypeReference::wrap(Lexer::Token(namedType.origin()), namedType)) }; >+ } >+ >+ ASSERT(is<AST::UnnamedType>(unifyNode)); >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ >+ if (is<AST::ArrayReferenceType>(unnamedType)) >+ return unnamedType.clone(); >+ >+ if (is<AST::ArrayType>(unnamedType)) >+ return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(unnamedType.origin()), addressSpace, downcast<AST::ArrayType>(unnamedType).type().clone()) }; >+ >+ if (is<AST::PointerType>(unnamedType)) >+ return WTF::nullopt; >+ >+ return { makeUniqueRef<AST::PointerType>(Lexer::Token(unnamedType.origin()), addressSpace, unnamedType.clone()) }; >+} >+ >+void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpression, ResolvingType* additionalArgumentType) > { >- auto baseInfo = recurseAndGetInfo(dotExpression.base()); >+ auto baseInfo = recurseAndGetInfo(propertyAccessExpression.base()); > if (!baseInfo) > return; > auto baseUnnamedType = commit(baseInfo->resolvingType); >@@ -979,65 +1005,101 @@ void Checker::visit(AST::DotExpression& > AST::UnnamedType* getterReturnType = nullptr; > { > Vector<std::reference_wrapper<ResolvingType>> getterArgumentTypes { baseInfo->resolvingType }; >- getterFunction = resolveFunctionOverload(dotExpression.possibleGetterOverloads(), getterArgumentTypes); >- if (getterFunction) >+ if (additionalArgumentType) >+ getterArgumentTypes.append(*additionalArgumentType); >+ if ((getterFunction = resolveFunctionOverload(propertyAccessExpression.possibleGetterOverloads(), getterArgumentTypes))) > getterReturnType = &getterFunction->type(); > } > > AST::FunctionDeclaration* anderFunction = nullptr; > AST::UnnamedType* anderReturnType = nullptr; >- if (auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace()) { >- auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), *leftAddressSpace, baseUnnamedType->get().clone()); >- Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { baseInfo->resolvingType }; >- anderFunction = resolveFunctionOverload(dotExpression.possibleAnderOverloads(), anderArgumentTypes); >- if (anderFunction) >- anderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer >+ auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace(); >+ if (leftAddressSpace) { >+ if (auto argumentTypeForAndOverload = WHLSL::argumentTypeForAndOverload(*baseUnnamedType, *leftAddressSpace)) { >+ ResolvingType argumentType = { WTFMove(*argumentTypeForAndOverload) }; >+ Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { argumentType }; >+ if (additionalArgumentType) >+ anderArgumentTypes.append(*additionalArgumentType); >+ if ((anderFunction = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes))) >+ anderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer >+ else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), anderArgumentTypes, m_intrinsics)) { >+ m_program.append(WTFMove(*newFunction)); >+ anderFunction = &m_program.nativeFunctionDeclarations().last(); >+ anderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer >+ } >+ } > } > > AST::FunctionDeclaration* threadAnderFunction = nullptr; > AST::UnnamedType* threadAnderReturnType = nullptr; >- { >- auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, baseUnnamedType->get().clone()); >- Vector<std::reference_wrapper<ResolvingType>> threadAnderArgumentTypes { baseInfo->resolvingType }; >- threadAnderFunction = resolveFunctionOverload(dotExpression.possibleAnderOverloads(), threadAnderArgumentTypes); >- if (threadAnderFunction) >+ if (auto argumentTypeForAndOverload = WHLSL::argumentTypeForAndOverload(*baseUnnamedType, AST::AddressSpace::Thread)) { >+ ResolvingType argumentType = { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, baseUnnamedType->get().clone()) }; >+ Vector<std::reference_wrapper<ResolvingType>> threadAnderArgumentTypes { argumentType }; >+ if (additionalArgumentType) >+ threadAnderArgumentTypes.append(*additionalArgumentType); >+ if ((threadAnderFunction = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes))) > threadAnderReturnType = &downcast<AST::PointerType>(threadAnderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer >+ else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), threadAnderArgumentTypes, m_intrinsics)) { >+ m_program.append(WTFMove(*newFunction)); >+ threadAnderFunction = &m_program.nativeFunctionDeclarations().last(); >+ threadAnderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer >+ } > } > >- if (!getterFunction && !anderFunction) { >+ if (leftAddressSpace && !anderFunction && !getterFunction) { > setError(); > return; > } >- if (getterFunction && anderFunction) { >+ >+ if (!leftAddressSpace && !threadAnderFunction && !getterFunction) { > setError(); > return; > } >+ >+ if (threadAnderFunction && getterFunction) { >+ setError(); >+ return; >+ } >+ > if (anderFunction && threadAnderFunction && !matches(*anderReturnType, *threadAnderReturnType)) { > setError(); > return; > } > >- AST::UnnamedType* fieldType = getterReturnType ? getterReturnType : anderReturnType; >+ if (getterFunction && anderFunction && !matches(*getterReturnType, *anderReturnType)) { >+ setError(); >+ return; >+ } >+ >+ if (getterFunction && threadAnderFunction && !matches(*getterReturnType, *threadAnderReturnType)) { >+ setError(); >+ return; >+ } >+ >+ AST::UnnamedType* fieldType = getterReturnType ? getterReturnType : anderReturnType ? anderReturnType : threadAnderReturnType; > > AST::FunctionDeclaration* setterFunction = nullptr; > AST::UnnamedType* setterReturnType = nullptr; > { > ResolvingType fieldResolvingType(fieldType->clone()); >- Vector<std::reference_wrapper<ResolvingType>> setterArgumentTypes { baseInfo->resolvingType, fieldResolvingType }; >- setterFunction = resolveFunctionOverload(dotExpression.possibleSetterOverloads(), setterArgumentTypes); >+ Vector<std::reference_wrapper<ResolvingType>> setterArgumentTypes { baseInfo->resolvingType }; >+ if (additionalArgumentType) >+ setterArgumentTypes.append(*additionalArgumentType); >+ setterArgumentTypes.append(fieldResolvingType); >+ setterFunction = resolveFunctionOverload(propertyAccessExpression.possibleSetterOverloads(), setterArgumentTypes); > if (setterFunction) > setterReturnType = &setterFunction->type(); > } > >- if (setterFunction && anderFunction) { >+ if (setterFunction && !getterFunction) { > setError(); > return; > } > >- dotExpression.setGetterFunction(getterFunction); >- dotExpression.setAnderFunction(anderFunction); >- dotExpression.setThreadAnderFunction(threadAnderFunction); >- dotExpression.setSetterFunction(setterFunction); >+ propertyAccessExpression.setGetterFunction(getterFunction); >+ propertyAccessExpression.setAnderFunction(anderFunction); >+ propertyAccessExpression.setThreadAnderFunction(threadAnderFunction); >+ propertyAccessExpression.setSetterFunction(setterFunction); > > AST::TypeAnnotation typeAnnotation = AST::RightValue(); > if (auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace()) { >@@ -1045,14 +1107,22 @@ void Checker::visit(AST::DotExpression& > typeAnnotation = AST::LeftValue { *leftAddressSpace }; > else if (setterFunction) > typeAnnotation = AST::AbstractLeftValue(); >- } else if (!baseInfo->typeAnnotation.isRightValue() && (setterFunction || anderFunction)) >+ } else if (!baseInfo->typeAnnotation.isRightValue() && (setterFunction || threadAnderFunction)) > typeAnnotation = AST::AbstractLeftValue(); >- assignType(dotExpression, fieldType->clone(), WTFMove(typeAnnotation)); >+ assignType(propertyAccessExpression, fieldType->clone(), WTFMove(typeAnnotation)); > } > >-void Checker::visit(AST::IndexExpression&) >+void Checker::visit(AST::DotExpression& dotExpression) > { >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198163 Implement this. >+ finishVisiting(dotExpression); >+} >+ >+void Checker::visit(AST::IndexExpression& indexExpression) >+{ >+ auto baseInfo = recurseAndGetInfo(indexExpression.indexExpression()); >+ if (!baseInfo) >+ return; >+ finishVisiting(indexExpression, &baseInfo->resolvingType); > } > > void Checker::visit(AST::VariableReference& variableReference) >@@ -1362,7 +1432,7 @@ void Checker::visit(AST::CommaExpression > if (error()) > return; > auto lastInfo = getInfo(commaExpression.list().last()); >- forwardType(commaExpression, lastInfo->resolvingType, lastInfo->typeAnnotation); >+ forwardType(commaExpression, lastInfo->resolvingType); > } > > void Checker::visit(AST::TernaryExpression& ternaryExpression) >@@ -1399,7 +1469,7 @@ void Checker::visit(AST::CallExpression& > ASSERT(callExpression.hasOverloads()); > auto* function = resolveFunctionOverload(*callExpression.overloads(), types, callExpression.castReturnType()); > if (!function) { >- if (auto newFunction = resolveByInstantiation(callExpression, types, m_intrinsics)) { >+ if (auto newFunction = resolveByInstantiation(callExpression.name(), callExpression.origin(), types, m_intrinsics)) { > m_program.append(WTFMove(*newFunction)); > function = &m_program.nativeFunctionDeclarations().last(); > } >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.cpp (nonexistent) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.cpp (working copy) >@@ -0,0 +1,91 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "WHLSLComputeDimensions.h" >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLFunctionDeclaration.h" >+#include "WHLSLPrepare.h" >+#include "WHLSLProgram.h" >+#include <wtf/Optional.h> >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class ComputeDimensionsVisitor : public Visitor { >+public: >+ ComputeDimensionsVisitor(AST::FunctionDefinition& entryPoint) >+ : m_entryPoint(entryPoint) >+ { >+ } >+ >+ virtual ~ComputeDimensionsVisitor() = default; >+ >+ Optional<ComputeDimensions> computeDimensions() const { return m_computeDimensions; } >+ >+private: >+ void visit(AST::FunctionDeclaration& functionDeclaration) override >+ { >+ Visitor::visit(functionDeclaration); >+ bool foundNumThreadsFunctionAttribute = false; >+ for (auto& functionAttribute : functionDeclaration.attributeBlock()) { >+ auto success = WTF::visit(WTF::makeVisitor([&](AST::NumThreadsFunctionAttribute& numThreadsFunctionAttribute) { >+ if (foundNumThreadsFunctionAttribute) >+ return false; >+ foundNumThreadsFunctionAttribute = true; >+ if (&functionDeclaration == &m_entryPoint) { >+ ASSERT(!m_computeDimensions); >+ m_computeDimensions = {{ numThreadsFunctionAttribute.width(), numThreadsFunctionAttribute.height(), numThreadsFunctionAttribute.depth() }}; >+ } >+ return true; >+ }), functionAttribute); >+ if (!success) { >+ setError(); >+ return; >+ } >+ } >+ } >+ >+ AST::FunctionDefinition& m_entryPoint; >+ Optional<ComputeDimensions> m_computeDimensions; >+}; >+ >+Optional<ComputeDimensions> computeDimensions(Program& program, AST::FunctionDefinition& entryPoint) >+{ >+ ComputeDimensionsVisitor computeDimensions(entryPoint); >+ computeDimensions.Visitor::visit(program); >+ if (computeDimensions.error()) >+ return WTF::nullopt; >+ return computeDimensions.computeDimensions(); >+} >+ >+} // namespace WHLSL >+ >+} // namespace WebCore >+ >+#endif // ENABLE(WEBGPU) >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.h (nonexistent) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLComputeDimensions.h (working copy) >@@ -0,0 +1,44 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLPrepare.h" >+ >+namespace WebCore { >+ >+namespace WHLSL { >+ >+class Program; >+ >+Optional<ComputeDimensions> computeDimensions(Program&, AST::FunctionDefinition&); >+ >+} >+ >+} >+ >+#endif >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp (working copy) >@@ -175,7 +175,8 @@ Optional<EntryPointItems> gatherEntryPoi > return WTF::nullopt; > } > Gatherer outputGatherer(intrinsics, functionDefinition.semantic() ? &*functionDefinition.semantic() : nullptr); >- outputGatherer.checkErrorAndVisit(functionDefinition.type()); >+ if (*functionDefinition.entryPointType() != AST::EntryPointType::Compute) >+ outputGatherer.checkErrorAndVisit(functionDefinition.type()); > if (outputGatherer.error()) > return WTF::nullopt; > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h (working copy) >@@ -47,7 +47,6 @@ class UnnamedType; > bool matches(const AST::UnnamedType&, const AST::UnnamedType&); > bool matches(const AST::NamedType&, const AST::NamedType&); > bool matches(const AST::UnnamedType&, const AST::NamedType&); >-// FIXME: Is anyone actually using the return type here? > Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::UnnamedType&, AST::ResolvableType&); > Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::NamedType&, AST::ResolvableType&); > Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(AST::ResolvableType&, AST::ResolvableType&); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h (working copy) >@@ -114,18 +114,28 @@ enum class ShaderStage : uint8_t { > Compute = 1 << 2 > }; > >-enum class BindingType : uint8_t { >- UniformBuffer, >- Sampler, >- Texture, >- StorageBuffer, >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198168 Add the dynamic types >+struct UniformBufferBinding { >+ unsigned lengthName; > }; > >+struct SamplerBinding { >+}; >+ >+struct TextureBinding { >+}; >+ >+struct StorageBufferBinding { >+ unsigned lengthName; >+}; >+ >+// FIXME: https://bugs.webkit.org/show_bug.cgi?id=198168 Add the dynamic types >+ > struct Binding { >+ using BindingDetails = Variant<UniformBufferBinding, SamplerBinding, TextureBinding, StorageBufferBinding>; > OptionSet<ShaderStage> visibility; >- BindingType bindingType; >- unsigned name; >+ BindingDetails binding; >+ unsigned internalName; >+ unsigned externalName; > }; > > struct BindGroup { >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (working copy) >@@ -32,6 +32,7 @@ > #include "WHLSLAutoInitializeVariables.h" > #include "WHLSLCheckDuplicateFunctions.h" > #include "WHLSLChecker.h" >+#include "WHLSLComputeDimensions.h" > #include "WHLSLFunctionStageChecker.h" > #include "WHLSLHighZombieFinder.h" > #include "WHLSLLiteralTypeChecker.h" >@@ -58,7 +59,7 @@ namespace WHLSL { > > static constexpr bool dumpASTBeforeEachPass = false; > static constexpr bool dumpASTAfterParsing = false; >-static constexpr bool dumpASTAtEnd = false; >+static constexpr bool dumpASTAtEnd = true; > static constexpr bool alwaysDumpPassFailures = false; > static constexpr bool dumpPassFailure = dumpASTBeforeEachPass || dumpASTAfterParsing || dumpASTAtEnd || alwaysDumpPassFailures; > >@@ -170,12 +171,16 @@ Optional<ComputePrepareResult> prepare(S > auto matchedSemantics = matchSemantics(*program, computePipelineDescriptor); > if (!matchedSemantics) > return WTF::nullopt; >+ auto computeDimensions = WHLSL::computeDimensions(*program, *matchedSemantics->shader); >+ if (!computeDimensions) >+ return WTF::nullopt; > > auto generatedCode = Metal::generateMetalCode(*program, WTFMove(*matchedSemantics), computePipelineDescriptor.layout); > > ComputePrepareResult result; > result.metalSource = WTFMove(generatedCode.metalSource); > result.mangledEntryPointName = WTFMove(generatedCode.mangledEntryPointName); >+ result.computeDimensions = WTFMove(*computeDimensions); > return result; > } > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.h (working copy) >@@ -42,9 +42,16 @@ struct RenderPrepareResult { > }; > Optional<RenderPrepareResult> prepare(String& whlslSource, RenderPipelineDescriptor&); > >+struct ComputeDimensions { >+ unsigned width; >+ unsigned height; >+ unsigned depth; >+}; >+ > struct ComputePrepareResult { > String metalSource; > String mangledEntryPointName; >+ ComputeDimensions computeDimensions; > }; > Optional<ComputePrepareResult> prepare(String& whlslSource, ComputePipelineDescriptor&); > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPreserveVariableLifetimes.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPreserveVariableLifetimes.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPreserveVariableLifetimes.cpp (working copy) >@@ -110,7 +110,7 @@ public: > > auto rhs = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variable)); > rhs->setType(variable.type()->clone()); >- rhs->setTypeAnnotation(AST::RightValue()); >+ rhs->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); > > auto assignment = makeUniqueRef<AST::AssignmentExpression>(variable.origin(), WTFMove(lhs), WTFMove(rhs)); > assignment->setType(variable.type()->clone()); >@@ -136,7 +136,7 @@ public: > > auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(functionDefinition.origin(), WTFMove(structVariableReference)); > makePointerExpression->setType(m_pointerToStructType->clone()); >- makePointerExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ makePointerExpression->setTypeAnnotation(AST::RightValue()); > > auto pointerDeclaration = makeUniqueRef<AST::VariableDeclaration>(functionDefinition.origin(), AST::Qualifiers(), > m_pointerToStructType->clone(), "wrapper"_s, WTF::nullopt, Optional<UniqueRef<AST::Expression>>(WTFMove(makePointerExpression))); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp (working copy) >@@ -35,6 +35,7 @@ > #include "WHLSLDotExpression.h" > #include "WHLSLFunctionDeclaration.h" > #include "WHLSLFunctionDefinition.h" >+#include "WHLSLMakeArrayReferenceExpression.h" > #include "WHLSLMakePointerExpression.h" > #include "WHLSLPointerType.h" > #include "WHLSLReadModifyWriteExpression.h" >@@ -51,10 +52,11 @@ public: > private: > void visit(AST::FunctionDefinition&) override; > void visit(AST::DotExpression&) override; >+ void visit(AST::IndexExpression&) override; > void visit(AST::AssignmentExpression&) override; > void visit(AST::ReadModifyWriteExpression&) override; > >- bool simplifyRightValue(AST::DotExpression&); >+ void simplifyRightValue(AST::PropertyAccessExpression&); > bool simplifyAbstractLeftValue(AST::AssignmentExpression&, AST::DotExpression&, UniqueRef<AST::Expression>&& right); > void simplifyLeftValue(AST::Expression&); > >@@ -64,8 +66,14 @@ private: > void PropertyResolver::visit(AST::DotExpression& dotExpression) > { > // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value. >- if (!simplifyRightValue(dotExpression)) >- setError(); >+ simplifyRightValue(dotExpression); >+} >+ >+void PropertyResolver::visit(AST::IndexExpression& indexExpression) >+{ >+ checkErrorAndVisit(indexExpression.indexExpression()); >+ // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value. >+ simplifyRightValue(indexExpression); > } > > void PropertyResolver::visit(AST::FunctionDefinition& functionDefinition) >@@ -75,79 +83,182 @@ void PropertyResolver::visit(AST::Functi > functionDefinition.block().statements().insert(0, makeUniqueRef<AST::VariableDeclarationsStatement>(Lexer::Token(m_variableDeclarations[0]->origin()), WTFMove(m_variableDeclarations))); > } > >-static Optional<UniqueRef<AST::Expression>> setterCall(AST::DotExpression& dotExpression, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory) >+enum class WhichAnder { >+ ThreadAnder, >+ Ander >+}; >+ >+struct AnderCallArgumentResult { >+ UniqueRef<AST::Expression> expression; >+ Optional<UniqueRef<AST::VariableDeclaration>> variableDeclaration; >+ WhichAnder whichAnder; >+}; >+ >+template <typename ExpressionConstructor, typename TypeConstructor> >+static Optional<AnderCallArgumentResult> wrapAnderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction) > { >- if (dotExpression.anderFunction()) { >- // *operator&.foo(&v) = newValue >- if (!dotExpression.threadAnderFunction()) >+ if (auto addressSpace = expression->typeAnnotation().leftAddressSpace()) { >+ if (!anderFunction) > return WTF::nullopt; >- >+ auto origin = expression->origin(); >+ auto baseType = expression->resolvedType().clone(); >+ auto makeArrayReference = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(expression)); >+ makeArrayReference->setType(makeUniqueRef<TypeConstructor>(WTFMove(origin), *addressSpace, WTFMove(baseType))); >+ makeArrayReference->setTypeAnnotation(AST::RightValue()); >+ return {{ WTFMove(makeArrayReference), WTF::nullopt, WhichAnder::Ander }}; >+ } >+ if (threadAnderFunction) { >+ auto origin = expression->origin(); >+ auto baseType = expression->resolvedType().clone(); >+ auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), baseType->clone(), String(), WTF::nullopt, WTF::nullopt); >+ >+ auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ variableReference1->setType(baseType->clone()); >+ variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), WTFMove(expression)); >+ assignmentExpression->setType(baseType->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >+ variableReference2->setType(baseType->clone()); >+ variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ >+ auto expression = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(variableReference2)); >+ auto resultType = makeUniqueRef<TypeConstructor>(Lexer::Token(origin), AST::AddressSpace::Thread, WTFMove(baseType)); >+ expression->setType(resultType->clone()); >+ expression->setTypeAnnotation(AST::RightValue()); >+ >+ Vector<UniqueRef<AST::Expression>> expressions; >+ expressions.append(WTFMove(assignmentExpression)); >+ expressions.append(WTFMove(expression)); >+ auto commaExpression = makeUniqueRef<AST::CommaExpression>(WTFMove(origin), WTFMove(expressions)); >+ commaExpression->setType(WTFMove(resultType)); >+ commaExpression->setTypeAnnotation(AST::RightValue()); >+ return {{ WTFMove(commaExpression), { WTFMove(variableDeclaration) }, WhichAnder::ThreadAnder}}; >+ } >+ return WTF::nullopt; >+} >+ >+static Optional<AnderCallArgumentResult> anderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction) >+{ >+ auto& unifyNode = expression->resolvedType().unifyNode(); >+ if (is<AST::UnnamedType>(unifyNode)) { >+ auto& unnamedType = downcast<AST::UnnamedType>(unifyNode); >+ ASSERT(!is<AST::PointerType>(unnamedType)); >+ if (is<AST::ArrayReferenceType>(unnamedType)) >+ return {{ WTFMove(expression), WTF::nullopt, WhichAnder::Ander }}; >+ if (is<AST::ArrayType>(unnamedType)) >+ return wrapAnderCallArgument<AST::MakeArrayReferenceExpression, AST::ArrayReferenceType>(expression, anderFunction, threadAnderFunction); >+ } >+ return wrapAnderCallArgument<AST::MakePointerExpression, AST::PointerType>(expression, anderFunction, threadAnderFunction); >+} >+ >+static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable) >+{ >+ auto maybeAddIndexArgument = [&](Vector<UniqueRef<AST::Expression>>& arguments) { >+ if (!indexVariable) >+ return; >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*indexVariable)); >+ ASSERT(indexVariable->type()); >+ variableReference->setType(indexVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >+ arguments.append(WTFMove(variableReference)); >+ }; >+ >+ if (relevantAnder) { >+ // *operator&.foo(&v) = newValue >+ auto leftValue = leftValueFactory(); >+ auto argument = anderCallArgument(leftValue, true, true); >+ ASSERT(argument); >+ ASSERT(!argument->variableDeclaration); >+ ASSERT(argument->whichAnder == WhichAnder::Ander); > Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(pointerToLeftValueFactory()); >- auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.threadAnderFunction()->name()), WTFMove(arguments)); >- callExpression->setType(dotExpression.threadAnderFunction()->type().clone()); >+ arguments.append(WTFMove(argument->expression)); >+ maybeAddIndexArgument(arguments); >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(relevantAnder->name()), WTFMove(arguments)); >+ callExpression->setType(relevantAnder->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.threadAnderFunction()); >+ callExpression->setFunction(*relevantAnder); > >- auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(callExpression)); >- dereferenceExpression->setType(downcast<AST::PointerType>(dotExpression.threadAnderFunction()->type()).elementType().clone()); >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(relevantAnder->type()).elementType().clone()); > dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); > >- auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), WTFMove(dereferenceExpression), WTFMove(newValue)); >- assignmentExpression->setType(downcast<AST::PointerType>(dotExpression.threadAnderFunction()->type()).elementType().clone()); >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(dereferenceExpression), WTFMove(newValue)); >+ assignmentExpression->setType(downcast<AST::PointerType>(relevantAnder->type()).elementType().clone()); > assignmentExpression->setTypeAnnotation(AST::RightValue()); > > return UniqueRef<AST::Expression>(WTFMove(assignmentExpression)); > } > > // v = operator.foo=(v, newValue) >- ASSERT(dotExpression.setterFunction()); >+ ASSERT(propertyAccessExpression.setterFunction()); > > Vector<UniqueRef<AST::Expression>> arguments; > arguments.append(leftValueFactory()); >+ maybeAddIndexArgument(arguments); > arguments.append(WTFMove(newValue)); >- auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.setterFunction()->name()), WTFMove(arguments)); >- callExpression->setType(dotExpression.setterFunction()->type().clone()); >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(propertyAccessExpression.setterFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(propertyAccessExpression.setterFunction()->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.setterFunction()); >+ callExpression->setFunction(*propertyAccessExpression.setterFunction()); > >- auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), leftValueFactory(), WTFMove(callExpression)); >- assignmentExpression->setType(dotExpression.setterFunction()->type().clone()); >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(propertyAccessExpression.origin()), leftValueFactory(), WTFMove(callExpression)); >+ assignmentExpression->setType(propertyAccessExpression.setterFunction()->type().clone()); > assignmentExpression->setTypeAnnotation(AST::RightValue()); > > return UniqueRef<AST::Expression>(WTFMove(assignmentExpression)); > } > >-static Optional<UniqueRef<AST::Expression>> getterCall(AST::DotExpression& dotExpression, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory) >+static Optional<UniqueRef<AST::Expression>> getterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable) > { >- if (dotExpression.anderFunction()) { >+ auto maybeAddIndexArgument = [&](Vector<UniqueRef<AST::Expression>>& arguments) { >+ if (!indexVariable) >+ return; >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*indexVariable)); >+ ASSERT(indexVariable->type()); >+ variableReference->setType(indexVariable->type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >+ arguments.append(WTFMove(variableReference)); >+ }; >+ >+ if (relevantAnder) { > // *operator&.foo(&v) >- if (!dotExpression.threadAnderFunction()) >- return WTF::nullopt; >- >+ auto leftValue = leftValueFactory(); >+ auto argument = anderCallArgument(leftValue, true, true); >+ ASSERT(argument); >+ ASSERT(!argument->variableDeclaration); >+ ASSERT(argument->whichAnder == WhichAnder::Ander); > Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(pointerToLeftValueFactory()); >- auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.threadAnderFunction()->name()), WTFMove(arguments)); >- callExpression->setType(dotExpression.threadAnderFunction()->type().clone()); >+ arguments.append(WTFMove(argument->expression)); >+ maybeAddIndexArgument(arguments); >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(relevantAnder->name()), WTFMove(arguments)); >+ callExpression->setType(relevantAnder->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.threadAnderFunction()); >+ callExpression->setFunction(*relevantAnder); > >- auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(callExpression)); >- dereferenceExpression->setType(downcast<AST::PointerType>(dotExpression.threadAnderFunction()->type()).elementType().clone()); >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(callExpression)); >+ dereferenceExpression->setType(downcast<AST::PointerType>(relevantAnder->type()).elementType().clone()); > dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); > > return UniqueRef<AST::Expression>(WTFMove(dereferenceExpression)); > } > > // operator.foo(v) >- ASSERT(dotExpression.getterFunction()); >- >+ ASSERT(propertyAccessExpression.getterFunction()); >+ > Vector<UniqueRef<AST::Expression>> arguments; > arguments.append(leftValueFactory()); >- auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(dotExpression.origin()), String(dotExpression.getterFunction()->name()), WTFMove(arguments)); >- callExpression->setType(dotExpression.getterFunction()->type().clone()); >+ maybeAddIndexArgument(arguments); >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(propertyAccessExpression.getterFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(propertyAccessExpression.getterFunction()->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.getterFunction()); >+ callExpression->setFunction(*propertyAccessExpression.getterFunction()); > > return UniqueRef<AST::Expression>(WTFMove(callExpression)); > } >@@ -161,7 +272,7 @@ struct ModificationResult { > Vector<UniqueRef<AST::Expression>> expressions; > UniqueRef<AST::Expression> result; > }; >-static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::function<Optional<ModificationResult>(Optional<UniqueRef<AST::Expression>>&&)> modification) >+static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAccessExpression, std::function<Optional<ModificationResult>(Optional<UniqueRef<AST::Expression>>&&)> modification) > { > // Consider a.b.c.d++; > // This would get transformed into: >@@ -181,22 +292,22 @@ static Optional<ModifyResult> modify(AST > // r = operator.d=(r, newValue); > // q = operator.c=(q, r); > // >- // Step 4: >+ // Step 5: > // *p = operator.b=(*p, q); > > // If the expression is a.b.c.d = e, Step 3 disappears and "newValue" in step 4 becomes "e". > > > // Find the ".b" ".c" and ".d" expressions. They end up in the order [".d", ".c", ".b"]. >- Vector<std::reference_wrapper<AST::DotExpression>> chain; >- AST::DotExpression* iterator = &dotExpression; >+ Vector<std::reference_wrapper<AST::PropertyAccessExpression>> chain; >+ AST::PropertyAccessExpression* iterator = &propertyAccessExpression; > while (true) { > chain.append(*iterator); > if (iterator->base().typeAnnotation().leftAddressSpace()) > break; > ASSERT(!iterator->base().typeAnnotation().isRightValue()); >- ASSERT(is<AST::DotExpression>(iterator->base())); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198163 Make this work with index expressions >- iterator = &downcast<AST::DotExpression>(iterator->base()); >+ ASSERT(is<AST::PropertyAccessExpression>(iterator->base())); >+ iterator = &downcast<AST::PropertyAccessExpression>(iterator->base()); > } > auto leftExpression = iterator->takeBase(); > AST::Expression& innerLeftExpression = leftExpression; >@@ -208,8 +319,39 @@ static Optional<ModifyResult> modify(AST > Vector<UniqueRef<AST::VariableDeclaration>> intermediateVariables; > intermediateVariables.reserveInitialCapacity(chain.size() - 1); > for (size_t i = 1; i < chain.size(); ++i) { >- auto& dotExpression = static_cast<AST::DotExpression&>(chain[i]); >- intermediateVariables.uncheckedAppend(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(dotExpression.origin()), AST::Qualifiers(), dotExpression.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt)); >+ auto& propertyAccessExpression = static_cast<AST::PropertyAccessExpression&>(chain[i]); >+ intermediateVariables.uncheckedAppend(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(propertyAccessExpression.origin()), AST::Qualifiers(), propertyAccessExpression.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt)); >+ } >+ >+ // Consider a[foo()][b] = c; >+ // Naively, This would get expanded to: >+ // >+ // temp = operator[](a, foo()); >+ // temp = operator[]=(temp, b, c); >+ // a = operator[]=(a, foo(), temp); >+ // >+ // However, if we did this, we would have to run foo() twice, which would be incorrect. >+ // Instead, we need to save foo() and b into more temporary variables. >+ // These temporary variables are parallel to "chain" above, with nullopt referring to a DotExpression (which doesn't have an index value to save to a variable). >+ // >+ // Instead, this gets expanded to: >+ // >+ // p = &a; >+ // temp = foo(); >+ // q = operator[](*p, temp); >+ // temp2 = b; >+ // q = operator[]=(q, temp2, c); >+ // *p = operator[]=(*p, temp, q); >+ >+ Vector<Optional<UniqueRef<AST::VariableDeclaration>>> indexVariables; >+ indexVariables.reserveInitialCapacity(chain.size()); >+ for (AST::PropertyAccessExpression& propertyAccessExpression : chain) { >+ if (!is<AST::IndexExpression>(propertyAccessExpression)) { >+ indexVariables.append(WTF::nullopt); >+ continue; >+ } >+ auto& indexExpression = downcast<AST::IndexExpression>(propertyAccessExpression); >+ indexVariables.uncheckedAppend(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(propertyAccessExpression.origin()), AST::Qualifiers(), indexExpression.indexExpression().resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt)); > } > > Vector<UniqueRef<AST::Expression>> expressions; >@@ -242,43 +384,44 @@ static Optional<ModifyResult> modify(AST > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > return variableReference; > } >- >+ > auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); > ASSERT(pointerVariable->type()); > variableReference->setType(pointerVariable->type()->clone()); > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > >- auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference)); > ASSERT(pointerVariable->type()); > dereferenceExpression->setType(downcast<AST::PointerType>(*pointerVariable->type()).elementType().clone()); > dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() }); > return dereferenceExpression; > }; >- auto pointerToPreviousLeftValue = [&]() -> UniqueRef<AST::Expression> { >- if (previous) { >- auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*previous)); >- ASSERT(previous->type()); >- variableReference->setType(previous->type()->clone()); >- variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >+ auto appendIndexAssignment = [&](AST::PropertyAccessExpression& propertyAccessExpression, Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable) { >+ if (!indexVariable) >+ return; >+ >+ auto& indexExpression = downcast<AST::IndexExpression>(propertyAccessExpression); >+ >+ auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*indexVariable)); >+ ASSERT(indexVariable->get().type()); >+ variableReference->setType(indexVariable->get().type()->clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >- ASSERT(previous->type()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone())); >- makePointerExpression->setTypeAnnotation(AST::RightValue()); >- return makePointerExpression; >- } >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference), indexExpression.takeIndex()); >+ assignmentExpression->setType(indexVariable->get().type()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); > >- auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >- ASSERT(pointerVariable->type()); >- variableReference->setType(pointerVariable->type()->clone()); >- variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >- return variableReference; >+ expressions.append(WTFMove(assignmentExpression)); > }; > for (size_t i = chain.size(); --i; ) { >- AST::DotExpression& dotExpression = chain[i]; >+ AST::PropertyAccessExpression& propertyAccessExpression = chain[i]; > AST::VariableDeclaration& variableDeclaration = intermediateVariables[i - 1]; >+ Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable = indexVariables[i]; > >- auto callExpression = getterCall(dotExpression, previousLeftValue, pointerToPreviousLeftValue); >+ appendIndexAssignment(propertyAccessExpression, indexVariable); >+ >+ AST::FunctionDeclaration* relevantAnder = i == chain.size() - 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction(); >+ auto callExpression = getterCall(propertyAccessExpression, relevantAnder, previousLeftValue, indexVariable ? &*indexVariable : nullptr); > > if (!callExpression) > return WTF::nullopt; >@@ -288,15 +431,17 @@ static Optional<ModifyResult> modify(AST > variableReference->setType(variableDeclaration.type()->clone()); > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > >- auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference), WTFMove(*callExpression)); >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference), WTFMove(*callExpression)); > assignmentExpression->setType(variableDeclaration.type()->clone()); > assignmentExpression->setTypeAnnotation(AST::RightValue()); > > expressions.append(WTFMove(assignmentExpression)); >- >+ > previous = &variableDeclaration; > } >- auto lastGetterCallExpression = getterCall(chain[0], previousLeftValue, pointerToPreviousLeftValue); >+ appendIndexAssignment(chain[0], indexVariables[0]); >+ AST::FunctionDeclaration* relevantAnder = chain.size() == 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction(); >+ auto lastGetterCallExpression = getterCall(chain[0], relevantAnder, previousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr); > > // Step 3: > auto modificationResult = modification(WTFMove(lastGetterCallExpression)); >@@ -309,27 +454,17 @@ static Optional<ModifyResult> modify(AST > UniqueRef<AST::Expression> rightValue = WTFMove(modificationResult->result); > auto expressionType = rightValue->resolvedType().clone(); > for (size_t i = 0; i < chain.size() - 1; ++i) { >- AST::DotExpression& dotExpression = chain[i]; >+ AST::PropertyAccessExpression& propertyAccessExpression = chain[i]; > AST::VariableDeclaration& variableDeclaration = intermediateVariables[i]; >+ Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable = indexVariables[i]; > >- auto assignmentExpression = setterCall(dotExpression, WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { >+ auto assignmentExpression = setterCall(propertyAccessExpression, propertyAccessExpression.threadAnderFunction(), WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { > auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); > ASSERT(variableDeclaration.type()); > variableReference->setType(variableDeclaration.type()->clone()); > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > return variableReference; >- }, [&]() -> UniqueRef<AST::Expression> { >- auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >- ASSERT(variableDeclaration.type()); >- variableReference->setType(variableDeclaration.type()->clone()); >- variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >- >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >- ASSERT(variableDeclaration.type()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone())); >- makePointerExpression->setTypeAnnotation(AST::RightValue()); >- return makePointerExpression; >- }); >+ }, indexVariable ? &*indexVariable : nullptr); > > if (!assignmentExpression) > return WTF::nullopt; >@@ -344,24 +479,19 @@ static Optional<ModifyResult> modify(AST > > // Step 5: > { >- auto assignmentExpression = setterCall(chain[chain.size() - 1], WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { >+ AST::PropertyAccessExpression& propertyAccessExpression = chain[chain.size() - 1]; >+ auto assignmentExpression = setterCall(propertyAccessExpression, propertyAccessExpression.anderFunction(), WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { > auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); > ASSERT(pointerVariable->type()); > variableReference->setType(pointerVariable->type()->clone()); > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > >- auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference)); > ASSERT(pointerVariable->type()); > dereferenceExpression->setType(downcast<AST::PointerType>(*pointerVariable->type()).elementType().clone()); > dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() }); > return dereferenceExpression; >- }, [&]() -> UniqueRef<AST::Expression> { >- auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable)); >- ASSERT(pointerVariable->type()); >- variableReference->setType(pointerVariable->type()->clone()); >- variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >- return variableReference; >- }); >+ }, indexVariables[indexVariables.size() - 1] ? &*(indexVariables[indexVariables.size() - 1]) : nullptr); > > if (!assignmentExpression) > return WTF::nullopt; >@@ -373,6 +503,10 @@ static Optional<ModifyResult> modify(AST > variableDeclarations.append(WTFMove(pointerVariable)); > for (auto& intermediateVariable : intermediateVariables) > variableDeclarations.append(WTFMove(intermediateVariable)); >+ for (auto& indexVariable : indexVariables) { >+ if (indexVariable) >+ variableDeclarations.append(WTFMove(*indexVariable)); >+ } > > return {{ innerLeftExpression, WTFMove(expressions), WTFMove(variableDeclarations) }}; > } >@@ -385,16 +519,13 @@ void PropertyResolver::visit(AST::Assign > return; > } > ASSERT(!assignmentExpression.left().typeAnnotation().isRightValue()); >- if (!is<AST::DotExpression>(assignmentExpression.left())) { >- setError(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198163 Make this work with index expressions. >- return; >- } >+ ASSERT(is<AST::PropertyAccessExpression>(assignmentExpression.left())); > > auto type = assignmentExpression.right().resolvedType().clone(); > > checkErrorAndVisit(assignmentExpression.right()); > >- auto modifyResult = modify(downcast<AST::DotExpression>(assignmentExpression.left()), [&](Optional<UniqueRef<AST::Expression>>&&) -> Optional<ModificationResult> { >+ auto modifyResult = modify(downcast<AST::PropertyAccessExpression>(assignmentExpression.left()), [&](Optional<UniqueRef<AST::Expression>>&&) -> Optional<ModificationResult> { > return {{ Vector<UniqueRef<AST::Expression>>(), assignmentExpression.takeRight() }}; > }); > >@@ -424,6 +555,8 @@ void PropertyResolver::visit(AST::ReadMo > // newValue = ...; > // *p = newValue; > >+ simplifyLeftValue(readModifyWriteExpression.leftValue()); >+ > auto baseType = readModifyWriteExpression.leftValue().resolvedType().clone(); > auto pointerType = makeUniqueRef<AST::PointerType>(Lexer::Token(readModifyWriteExpression.leftValue().origin()), *readModifyWriteExpression.leftValue().typeAnnotation().leftAddressSpace(), baseType->clone()); > >@@ -520,11 +653,11 @@ void PropertyResolver::visit(AST::ReadMo > } > > ASSERT(!readModifyWriteExpression.leftValue().typeAnnotation().isRightValue()); >- if (!is<AST::DotExpression>(readModifyWriteExpression.leftValue())) { >- setError(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198163 Make this work with index expressions. >+ if (!is<AST::PropertyAccessExpression>(readModifyWriteExpression.leftValue())) { >+ setError(); > return; > } >- auto modifyResult = modify(downcast<AST::DotExpression>(readModifyWriteExpression.leftValue()), [&](Optional<UniqueRef<AST::Expression>>&& lastGetterCallExpression) -> Optional<ModificationResult> { >+ auto modifyResult = modify(downcast<AST::PropertyAccessExpression>(readModifyWriteExpression.leftValue()), [&](Optional<UniqueRef<AST::Expression>>&& lastGetterCallExpression) -> Optional<ModificationResult> { > Vector<UniqueRef<AST::Expression>> expressions; > if (!lastGetterCallExpression) > return WTF::nullopt; >@@ -554,7 +687,11 @@ void PropertyResolver::visit(AST::ReadMo > expressions.append(WTFMove(assignmentExpression)); > } > >- return {{ WTFMove(expressions), readModifyWriteExpression.newVariableReference() }}; >+ auto variableReference = readModifyWriteExpression.newVariableReference(); >+ variableReference->setType(readModifyWriteExpression.leftValue().resolvedType().clone()); >+ variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? >+ >+ return {{ WTFMove(expressions), WTFMove(variableReference) }}; > }); > > if (!modifyResult) { >@@ -581,128 +718,107 @@ void PropertyResolver::visit(AST::ReadMo > m_variableDeclarations.append(WTFMove(newVariableDeclaration)); > } > >-bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) >+static Optional<AnderCallArgumentResult> anderCallArgument(AST::PropertyAccessExpression& propertyAccessExpression) > { >- Lexer::Token origin = dotExpression.origin(); >- >- checkErrorAndVisit(dotExpression.base()); >- >- if (auto* anderFunction = dotExpression.anderFunction()) { >- auto& base = dotExpression.base(); >- if (auto leftAddressSpace = base.typeAnnotation().leftAddressSpace()) { >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), dotExpression.takeBase()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), *leftAddressSpace, base.resolvedType().clone())); >- makePointerExpression->setTypeAnnotation(AST::RightValue()); >- >- Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(WTFMove(makePointerExpression)); >- auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments)); >- callExpression->setType(anderFunction->type().clone()); >- callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*anderFunction); >- >- auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(dotExpression, WTFMove(origin), WTFMove(callExpression)); >- dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone()); >- dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() }); >- return true; >- } >- >- // We have an ander, but no left value to call it on. Let's save the value into a temporary variable to create a left value. >- // This is effectively inlining the functions the spec says are generated. >- if (!dotExpression.threadAnderFunction()) >- return false; >- >- auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), base.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt); >- >- auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >- variableReference1->setType(base.resolvedType().clone()); >- variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >- >- auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), dotExpression.takeBase()); >- assignmentExpression->setType(base.resolvedType().clone()); >- assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ return anderCallArgument(propertyAccessExpression.baseReference(), propertyAccessExpression.anderFunction(), propertyAccessExpression.threadAnderFunction()); >+} > >- auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); >- variableReference2->setType(base.resolvedType().clone()); >- variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+void PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression) >+{ >+ Lexer::Token origin = propertyAccessExpression.origin(); > >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), WTFMove(variableReference2)); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), AST::AddressSpace::Thread, base.resolvedType().clone())); >- makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ checkErrorAndVisit(propertyAccessExpression.base()); > >+ if (auto argument = anderCallArgument(propertyAccessExpression)) { >+ auto* anderFunction = argument->whichAnder == WhichAnder::ThreadAnder ? propertyAccessExpression.threadAnderFunction() : propertyAccessExpression.anderFunction(); >+ ASSERT(anderFunction); >+ auto origin = propertyAccessExpression.origin(); > Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(WTFMove(makePointerExpression)); >+ arguments.append(WTFMove(argument->expression)); >+ if (is<AST::IndexExpression>(propertyAccessExpression)) >+ arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex()); > auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments)); > callExpression->setType(anderFunction->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); > callExpression->setFunction(*anderFunction); > >- auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(WTFMove(origin), WTFMove(callExpression)); >+ auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression)); > dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone()); >- dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() }); > >- Vector<UniqueRef<AST::Expression>> expressions; >- expressions.append(WTFMove(assignmentExpression)); >- expressions.append(WTFMove(dereferenceExpression)); >- auto* commaExpression = AST::replaceWith<AST::CommaExpression>(dotExpression, WTFMove(origin), WTFMove(expressions)); >- commaExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone()); >- commaExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); >+ if (auto& variableDeclaration = argument->variableDeclaration) >+ m_variableDeclarations.append(WTFMove(*variableDeclaration)); > >- m_variableDeclarations.append(WTFMove(variableDeclaration)); >- return true; >+ return; > } > >- ASSERT(dotExpression.getterFunction()); >- auto& getterFunction = *dotExpression.getterFunction(); >+ ASSERT(propertyAccessExpression.getterFunction()); >+ auto& getterFunction = *propertyAccessExpression.getterFunction(); > Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(dotExpression.takeBase()); >- auto* callExpression = AST::replaceWith<AST::CallExpression>(dotExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments)); >+ arguments.append(propertyAccessExpression.takeBase()); >+ if (is<AST::IndexExpression>(propertyAccessExpression)) >+ arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex()); >+ auto* callExpression = AST::replaceWith<AST::CallExpression>(propertyAccessExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments)); > callExpression->setFunction(getterFunction); > callExpression->setType(getterFunction.type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- return true; > } > > class LeftValueSimplifier : public Visitor { >-public: >+private: > void visit(AST::DotExpression&) override; >+ void visit(AST::IndexExpression&) override; > void visit(AST::DereferenceExpression&) override; > >-private: >+ void finishVisiting(AST::PropertyAccessExpression&); > }; > >-void LeftValueSimplifier::visit(AST::DotExpression& dotExpression) >+void LeftValueSimplifier::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpression) > { >- Visitor::visit(dotExpression); >- ASSERT(dotExpression.base().typeAnnotation().leftAddressSpace()); >- ASSERT(dotExpression.anderFunction()); >+ ASSERT(propertyAccessExpression.base().typeAnnotation().leftAddressSpace()); >+ ASSERT(propertyAccessExpression.anderFunction()); >+ >+ Visitor::visit(propertyAccessExpression.base()); >+ >+ Lexer::Token origin = propertyAccessExpression.origin(); >+ auto* anderFunction = propertyAccessExpression.anderFunction(); > >- Lexer::Token origin = dotExpression.origin(); >- auto* anderFunction = dotExpression.anderFunction(); >- auto& base = dotExpression.base(); >- auto leftAddressSpace = *dotExpression.base().typeAnnotation().leftAddressSpace(); >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), dotExpression.takeBase()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), leftAddressSpace, base.resolvedType().clone())); >- makePointerExpression->setTypeAnnotation(AST::RightValue()); >+ auto argument = anderCallArgument(propertyAccessExpression); >+ ASSERT(argument); >+ ASSERT(!argument->variableDeclaration); >+ ASSERT(argument->whichAnder == WhichAnder::Ander); > > Vector<UniqueRef<AST::Expression>> arguments; >- arguments.append(WTFMove(makePointerExpression)); >+ arguments.append(WTFMove(argument->expression)); >+ if (is<AST::IndexExpression>(propertyAccessExpression)) >+ arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex()); > auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments)); > callExpression->setType(anderFunction->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); > callExpression->setFunction(*anderFunction); > >- auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(dotExpression, WTFMove(origin), WTFMove(callExpression)); >+ auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression)); > dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone()); > dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() }); > } > >+void LeftValueSimplifier::visit(AST::DotExpression& dotExpression) >+{ >+ Visitor::visit(dotExpression); >+ finishVisiting(dotExpression); >+} >+ >+void LeftValueSimplifier::visit(AST::IndexExpression& indexExpression) >+{ >+ PropertyResolver().Visitor::visit(indexExpression.indexExpression()); >+ finishVisiting(indexExpression); >+} >+ > void LeftValueSimplifier::visit(AST::DereferenceExpression& dereferenceExpression) > { > // Dereference expressions are the only expressions where the children might be more-right than we are. > // For example, a dereference expression may be a left value but its child may be a call expression which is a right value. > // LeftValueSimplifier doesn't handle right values, so we instead need to use PropertyResolver. >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198170 What about function call arguments? > PropertyResolver().Visitor::visit(dereferenceExpression); > } > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp (working copy) >@@ -55,19 +55,17 @@ static AST::FunctionDefinition* findEntr > return &*iterator; > }; > >-static bool matchMode(BindingType bindingType, AST::ResourceSemantic::Mode mode) >+static bool matchMode(Binding::BindingDetails bindingType, AST::ResourceSemantic::Mode mode) > { >- switch (bindingType) { >- case BindingType::UniformBuffer: >+ return WTF::visit(WTF::makeVisitor([&](UniformBufferBinding) -> bool { > return mode == AST::ResourceSemantic::Mode::Buffer; >- case BindingType::Sampler: >+ }, [&](SamplerBinding) -> bool { > return mode == AST::ResourceSemantic::Mode::Sampler; >- case BindingType::Texture: >+ }, [&](TextureBinding) -> bool { > return mode == AST::ResourceSemantic::Mode::Texture; >- default: >- ASSERT(bindingType == BindingType::StorageBuffer); >+ }, [&](StorageBufferBinding) -> bool { > return mode == AST::ResourceSemantic::Mode::UnorderedAccessView; >- } >+ }), bindingType); > } > > static Optional<HashMap<Binding*, size_t>> matchResources(Vector<EntryPointItem>& entryPointItems, Layout& layout, ShaderStage shaderStage) >@@ -87,9 +85,9 @@ static Optional<HashMap<Binding*, size_t > if (!WTF::holds_alternative<AST::ResourceSemantic>(semantic)) > continue; > auto& resourceSemantic = WTF::get<AST::ResourceSemantic>(semantic); >- if (!matchMode(binding.bindingType, resourceSemantic.mode())) >+ if (!matchMode(binding.binding, resourceSemantic.mode())) > continue; >- if (binding.name != resourceSemantic.index()) >+ if (binding.externalName != resourceSemantic.index()) > continue; > if (space != resourceSemantic.space()) > continue; >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (working copy) >@@ -375,14 +375,62 @@ native typedef TextureDepth2DArray<float > native typedef RWTextureDepth2DArray<float>; > native typedef TextureDepthCube<float>; > >-native float operator.x(float4); >-native float operator.y(float4); >-native float operator.z(float4); >-native float operator.w(float4); >-native float4 operator.x=(float4, float); >-native float4 operator.y=(float4, float); >-native float4 operator.z=(float4, float); >-native float4 operator.w=(float4, float); >+native operator uchar(ushort); >+native operator uchar(uint); >+native operator uchar(char); >+native operator uchar(short); >+native operator uchar(int); >+native operator uchar(half); >+native operator uchar(float); >+native operator ushort(uchar); >+native operator ushort(uint); >+native operator ushort(char); >+native operator ushort(short); >+native operator ushort(int); >+native operator ushort(half); >+native operator ushort(float); >+native operator uint(uchar); >+native operator uint(ushort); >+native operator uint(char); >+native operator uint(short); >+native operator uint(int); >+native operator uint(half); >+native operator uint(float); >+native operator char(uchar); >+native operator char(ushort); >+native operator char(uint); >+native operator char(short); >+native operator char(int); >+native operator char(half); >+native operator char(float); >+native operator short(uchar); >+native operator short(ushort); >+native operator short(uint); >+native operator short(char); >+native operator short(int); >+native operator short(half); >+native operator short(float); >+native operator int(uchar); >+native operator int(ushort); >+native operator int(uint); >+native operator int(char); >+native operator int(short); >+native operator int(half); >+native operator int(float); >+native operator half(uchar); >+native operator half(ushort); >+native operator half(uint); >+native operator half(char); >+native operator half(short); >+native operator half(int); >+native operator half(float); >+native operator float(uchar); >+native operator float(ushort); >+native operator float(uint); >+native operator float(char); >+native operator float(short); >+native operator float(int); >+native operator float(half); > > native float operator+(float, float); > native float operator-(float, float); >@@ -391,6 +439,171 @@ native uint operator+(uint, uint); > native bool operator<(int, int); > native bool operator<(uint, uint); > native bool operator<(float, float); >+native float operator*(float, float); >+native bool operator==(float, float); >+ >+/* native bool operator.x(bool2); >+native bool operator.y(bool2); >+native bool operator.x(bool3); >+native bool operator.y(bool3); >+native bool operator.z(bool3); >+native bool operator.x(bool4); >+native bool operator.y(bool4); >+native bool operator.z(bool4); >+native bool operator.w(bool4); >+native bool2 operator.x=(bool2, bool); >+native bool2 operator.y=(bool2, bool); >+native bool3 operator.x=(bool3, bool); >+native bool3 operator.y=(bool3, bool); >+native bool3 operator.z=(bool3, bool); >+native bool4 operator.x=(bool4, bool); >+native bool4 operator.y=(bool4, bool); >+native bool4 operator.z=(bool4, bool); >+native bool4 operator.w=(bool4, bool); >+native uchar operator.x(uchar2); >+native uchar operator.y(uchar2); >+native uchar operator.x(uchar3); >+native uchar operator.y(uchar3); >+native uchar operator.z(uchar3); >+native uchar operator.x(uchar4); >+native uchar operator.y(uchar4); >+native uchar operator.z(uchar4); >+native uchar operator.w(uchar4); >+native uchar2 operator.x=(uchar2, uchar); >+native uchar2 operator.y=(uchar2, uchar); >+native uchar3 operator.x=(uchar3, uchar); >+native uchar3 operator.y=(uchar3, uchar); >+native uchar3 operator.z=(uchar3, uchar); >+native uchar4 operator.x=(uchar4, uchar); >+native uchar4 operator.y=(uchar4, uchar); >+native uchar4 operator.z=(uchar4, uchar); >+native uchar4 operator.w=(uchar4, uchar); >+native ushort operator.x(ushort2); >+native ushort operator.y(ushort2); >+native ushort operator.x(ushort3); >+native ushort operator.y(ushort3); >+native ushort operator.z(ushort3); >+native ushort operator.x(ushort4); >+native ushort operator.y(ushort4); >+native ushort operator.z(ushort4); >+native ushort operator.w(ushort4); >+native ushort2 operator.x=(ushort2, ushort); >+native ushort2 operator.y=(ushort2, ushort); >+native ushort3 operator.x=(ushort3, ushort); >+native ushort3 operator.y=(ushort3, ushort); >+native ushort3 operator.z=(ushort3, ushort); >+native ushort4 operator.x=(ushort4, ushort); >+native ushort4 operator.y=(ushort4, ushort); >+native ushort4 operator.z=(ushort4, ushort); >+native ushort4 operator.w=(ushort4, ushort); >+native uint operator.x(uint2); >+native uint operator.y(uint2); >+native uint operator.x(uint3); >+native uint operator.y(uint3); >+native uint operator.z(uint3); >+native uint operator.x(uint4); >+native uint operator.y(uint4); >+native uint operator.z(uint4); >+native uint operator.w(uint4); >+native uint2 operator.x=(uint2, uint); >+native uint2 operator.y=(uint2, uint); >+native uint3 operator.x=(uint3, uint); >+native uint3 operator.y=(uint3, uint); >+native uint3 operator.z=(uint3, uint); >+native uint4 operator.x=(uint4, uint); >+native uint4 operator.y=(uint4, uint); >+native uint4 operator.z=(uint4, uint); >+native uint4 operator.w=(uint4, uint); >+native char operator.x(char2); >+native char operator.y(char2); >+native char operator.x(char3); >+native char operator.y(char3); >+native char operator.z(char3); >+native char operator.x(char4); >+native char operator.y(char4); >+native char operator.z(char4); >+native char operator.w(char4); >+native char2 operator.x=(char2, char); >+native char2 operator.y=(char2, char); >+native char3 operator.x=(char3, char); >+native char3 operator.y=(char3, char); >+native char3 operator.z=(char3, char); >+native char4 operator.x=(char4, char); >+native char4 operator.y=(char4, char); >+native char4 operator.z=(char4, char); >+native char4 operator.w=(char4, char); >+native short operator.x(short2); >+native short operator.y(short2); >+native short operator.x(short3); >+native short operator.y(short3); >+native short operator.z(short3); >+native short operator.x(short4); >+native short operator.y(short4); >+native short operator.z(short4); >+native short operator.w(short4); >+native short2 operator.x=(short2, short); >+native short2 operator.y=(short2, short); >+native short3 operator.x=(short3, short); >+native short3 operator.y=(short3, short); >+native short3 operator.z=(short3, short); >+native short4 operator.x=(short4, short); >+native short4 operator.y=(short4, short); >+native short4 operator.z=(short4, short); >+native short4 operator.w=(short4, short); >+native int operator.x(int2); >+native int operator.y(int2); >+native int operator.x(int3); >+native int operator.y(int3); >+native int operator.z(int3); >+native int operator.x(int4); >+native int operator.y(int4); >+native int operator.z(int4); >+native int operator.w(int4); >+native int2 operator.x=(int2, int); >+native int2 operator.y=(int2, int); >+native int3 operator.x=(int3, int); >+native int3 operator.y=(int3, int); >+native int3 operator.z=(int3, int); >+native int4 operator.x=(int4, int); >+native int4 operator.y=(int4, int); >+native int4 operator.z=(int4, int); >+native int4 operator.w=(int4, int); >+native half operator.x(half2); >+native half operator.y(half2); >+native half operator.x(half3); >+native half operator.y(half3); >+native half operator.z(half3); >+native half operator.x(half4); >+native half operator.y(half4); >+native half operator.z(half4); >+native half operator.w(half4); >+native half2 operator.x=(half2, half); >+native half2 operator.y=(half2, half); >+native half3 operator.x=(half3, half); >+native half3 operator.y=(half3, half); >+native half3 operator.z=(half3, half); >+native half4 operator.x=(half4, half); >+native half4 operator.y=(half4, half); >+native half4 operator.z=(half4, half); >+native half4 operator.w=(half4, half); >+native float operator.x(float2); >+native float operator.y(float2);*/ >+native float operator.x(float3); >+native float operator.y(float3); >+native float operator.z(float3); >+native float operator.x(float4); >+native float operator.y(float4); >+native float operator.z(float4); >+native float operator.w(float4);/* >+native float2 operator.x=(float2, float); >+native float2 operator.y=(float2, float);*/ >+native float3 operator.x=(float3, float); >+native float3 operator.y=(float3, float); >+native float3 operator.z=(float3, float); >+native float4 operator.x=(float4, float); >+native float4 operator.y=(float4, float); >+native float4 operator.z=(float4, float); >+native float4 operator.w=(float4, float); > > native float ddx(float); > native float ddy(float); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp (working copy) >@@ -44,28 +44,6 @@ bool synthesizeStructureAccessors(Progra > bool isOperator = true; > for (auto& structureDefinition : program.structureDefinitions()) { > for (auto& structureElement : structureDefinition->structureElements()) { >- { >- // The getter: operator.field >- auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)), String(), WTF::nullopt, WTF::nullopt); >- AST::VariableDeclarations parameters; >- parameters.append(WTFMove(variableDeclaration)); >- AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(structureElement.origin()), AST::AttributeBlock(), WTF::nullopt, structureElement.type().clone(), makeString("operator.", structureElement.name()), WTFMove(parameters), WTF::nullopt, isOperator)); >- if (!program.append(WTFMove(nativeFunctionDeclaration))) >- return false; >- } >- >- { >- // The setter: operator.field= >- auto variableDeclaration1 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)), String(), WTF::nullopt, WTF::nullopt); >- auto variableDeclaration2 = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(structureElement.origin()), AST::Qualifiers(), structureElement.type().clone(), String(), WTF::nullopt, WTF::nullopt); >- AST::VariableDeclarations parameters; >- parameters.append(WTFMove(variableDeclaration1)); >- parameters.append(WTFMove(variableDeclaration2)); >- AST::NativeFunctionDeclaration nativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(structureElement.origin()), AST::AttributeBlock(), WTF::nullopt, AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition), makeString("operator.", structureElement.name(), '='), WTFMove(parameters), WTF::nullopt, isOperator)); >- if (!program.append(WTFMove(nativeFunctionDeclaration))) >- return false; >- } >- > // The ander: operator&.field > auto createAnder = [&](AST::AddressSpace addressSpace) -> AST::NativeFunctionDeclaration { > auto argumentType = makeUniqueRef<AST::PointerType>(Lexer::Token(structureElement.origin()), addressSpace, AST::TypeReference::wrap(Lexer::Token(structureElement.origin()), structureDefinition)); >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h (working copy) >@@ -43,7 +43,7 @@ enum class AddressSpace : uint8_t { > Thread > }; > >-static ALWAYS_INLINE String toString(AddressSpace addressSpace) >+ALWAYS_INLINE String toString(AddressSpace addressSpace) > { > switch (addressSpace) { > case AddressSpace::Constant: >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h (working copy) >@@ -41,7 +41,7 @@ enum class EntryPointType : uint8_t { > Compute, > }; > >-static ALWAYS_INLINE String toString(EntryPointType type) >+ALWAYS_INLINE String toString(EntryPointType type) > { > switch (type) { > case EntryPointType::Vertex: >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h (working copy) >@@ -59,15 +59,16 @@ public: > > String setterFunctionName() const override > { >- return "operator&[]"_str; >+ return "operator[]="_str; > } > > String anderFunctionName() const override > { >- return "operator[]="_str; >+ return "operator&[]"_str; > } > > Expression& indexExpression() { return m_index; } >+ UniqueRef<Expression> takeIndex() { return WTFMove(m_index); } > > private: > UniqueRef<Expression> m_index; >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h (working copy) >@@ -99,6 +99,7 @@ public: > } > > Expression& base() { return m_base; } >+ UniqueRef<Expression>& baseReference() { return m_base; } > UniqueRef<Expression> takeBase() { return WTFMove(m_base); } > > private: >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h (working copy) >@@ -53,7 +53,7 @@ public: > ReferenceType(const ReferenceType&) = delete; > ReferenceType(ReferenceType&&) = default; > >- bool isReferenceType() const override { return false; } >+ bool isReferenceType() const override { return true; } > > AddressSpace addressSpace() const { return m_addressSpace; } > const UnnamedType& elementType() const { return m_elementType; } >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp (working copy) >@@ -49,8 +49,6 @@ bool ResourceSemantic::isAcceptableType( > auto& referenceType = downcast<ReferenceType>(unnamedType); > return referenceType.addressSpace() == AddressSpace::Constant || referenceType.addressSpace() == AddressSpace::Device; > } >- if (is<ArrayType>(unnamedType)) >- return true; > if (is<TypeReference>(unnamedType)) { > auto& typeReference = downcast<TypeReference>(unnamedType); > if (is<NativeTypeDeclaration>(typeReference.resolvedType())) >@@ -71,7 +69,7 @@ bool ResourceSemantic::isAcceptableType( > case Mode::Buffer: > if (is<ReferenceType>(unnamedType)) > return downcast<ReferenceType>(unnamedType).addressSpace() == AddressSpace::Constant; >- return is<ArrayType>(unnamedType); >+ return false; > case Mode::Sampler: > return matches(unnamedType, intrinsics.samplerType()); > } >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp (working copy) >@@ -32,6 +32,7 @@ > #include "WHLSLFunctionDefinition.h" > #include "WHLSLGatherEntryPointItems.h" > #include "WHLSLPipelineDescriptor.h" >+#include "WHLSLReferenceType.h" > #include "WHLSLResourceSemantic.h" > #include "WHLSLStageInOutSemantic.h" > #include "WHLSLStructureDefinition.h" >@@ -108,7 +109,16 @@ EntryPointScaffolding::EntryPointScaffol > for (size_t j = 0; j < m_layout[i].bindings.size(); ++j) { > NamedBinding namedBinding; > namedBinding.elementName = m_typeNamer.generateNextStructureElementName(); >- namedBinding.index = m_layout[i].bindings[j].name; // GPUBindGroupLayout::tryCreate() makes sure these don't collide. >+ namedBinding.index = m_layout[i].bindings[j].internalName; >+ WTF::visit(WTF::makeVisitor([&](UniformBufferBinding& uniformBufferBinding) { >+ LengthInformation lengthInformation { m_typeNamer.generateNextStructureElementName(), m_generateNextVariableName(), uniformBufferBinding.lengthName }; >+ namedBinding.lengthInformation = lengthInformation; >+ }, [&](SamplerBinding&) { >+ }, [&](TextureBinding&) { >+ }, [&](StorageBufferBinding& storageBufferBinding) { >+ LengthInformation lengthInformation { m_typeNamer.generateNextStructureElementName(), m_generateNextVariableName(), storageBufferBinding.lengthName }; >+ namedBinding.lengthInformation = lengthInformation; >+ }), m_layout[i].bindings[j].binding); > namedBindGroup.namedBindings.uncheckedAppend(WTFMove(namedBinding)); > } > m_namedBindGroups.uncheckedAppend(WTFMove(namedBindGroup)); >@@ -137,10 +147,16 @@ String EntryPointScaffolding::resourceHe > auto iterator = m_resourceMap.find(&m_layout[i].bindings[j]); > if (iterator == m_resourceMap.end()) > continue; >- auto mangledTypeName = m_typeNamer.mangledNameForType(*m_entryPointItems.inputs[iterator->value].unnamedType); >+ auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType; >+ ASSERT(is<AST::ReferenceType>(unnamedType)); >+ auto& referenceType = downcast<AST::ReferenceType>(unnamedType); >+ auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType()); >+ auto addressSpace = toString(referenceType.addressSpace()); > auto elementName = m_namedBindGroups[i].namedBindings[j].elementName; > auto index = m_namedBindGroups[i].namedBindings[j].index; >- stringBuilder.append(makeString(" ", mangledTypeName, ' ', elementName, " [[id(", index, ")]];\n")); >+ stringBuilder.append(makeString(" ", addressSpace, " ", mangledTypeName, "* ", elementName, " [[id(", index, ")]];\n")); >+ if (auto lengthInformation = m_namedBindGroups[i].namedBindings[j].lengthInformation) >+ stringBuilder.append(makeString(" uint2 ", lengthInformation->elementName, " [[id(", lengthInformation->index, ")]];\n")); > } > stringBuilder.append("};\n\n"); > } >@@ -162,6 +178,41 @@ Optional<String> EntryPointScaffolding:: > return stringBuilder.toString(); > } > >+static String internalTypeForSemantic(const AST::BuiltInSemantic& builtInSemantic) >+{ >+ switch (builtInSemantic.variable()) { >+ case AST::BuiltInSemantic::Variable::SVInstanceID: >+ return "uint"_str; >+ case AST::BuiltInSemantic::Variable::SVVertexID: >+ return "uint"_str; >+ case AST::BuiltInSemantic::Variable::PSize: >+ return "float"_str; >+ case AST::BuiltInSemantic::Variable::SVPosition: >+ return "float4"_str; >+ case AST::BuiltInSemantic::Variable::SVIsFrontFace: >+ return "bool"_str; >+ case AST::BuiltInSemantic::Variable::SVSampleIndex: >+ return "uint"_str; >+ case AST::BuiltInSemantic::Variable::SVInnerCoverage: >+ return "uint"_str; >+ case AST::BuiltInSemantic::Variable::SVTarget: >+ return String(); >+ case AST::BuiltInSemantic::Variable::SVDepth: >+ return "float"_str; >+ case AST::BuiltInSemantic::Variable::SVCoverage: >+ return "uint"_str; >+ case AST::BuiltInSemantic::Variable::SVDispatchThreadID: >+ return "uint3"_str; >+ case AST::BuiltInSemantic::Variable::SVGroupID: >+ return "uint3"_str; >+ case AST::BuiltInSemantic::Variable::SVGroupIndex: >+ return "uint"_str; >+ default: >+ ASSERT(builtInSemantic.variable() == AST::BuiltInSemantic::Variable::SVGroupThreadID); >+ return "uint3"_str; >+ } >+} >+ > Optional<String> EntryPointScaffolding::builtInsSignature() > { > if (!m_namedBuiltIns.size()) >@@ -174,9 +225,11 @@ Optional<String> EntryPointScaffolding:: > auto& namedBuiltIn = m_namedBuiltIns[i]; > auto& item = m_entryPointItems.inputs[namedBuiltIn.indexInEntryPointItems]; > auto& builtInSemantic = WTF::get<AST::BuiltInSemantic>(*item.semantic); >- auto mangledTypeName = m_typeNamer.mangledNameForType(*item.unnamedType); >+ auto internalType = internalTypeForSemantic(builtInSemantic); >+ if (internalType.isNull()) >+ internalType = m_typeNamer.mangledNameForType(*item.unnamedType); > auto variableName = namedBuiltIn.variableName; >- stringBuilder.append(makeString(mangledTypeName, ' ', variableName, ' ', attributeForSemantic(builtInSemantic))); >+ stringBuilder.append(makeString(internalType, ' ', variableName, ' ', attributeForSemantic(builtInSemantic))); > } > return stringBuilder.toString(); > } >@@ -257,16 +310,37 @@ String EntryPointScaffolding::unpackReso > auto iterator = m_resourceMap.find(&m_layout[i].bindings[j]); > if (iterator == m_resourceMap.end()) > continue; >- auto& path = m_entryPointItems.inputs[iterator->value].path; >- auto elementName = m_namedBindGroups[i].namedBindings[j].elementName; >- stringBuilder.append(makeString(mangledInputPath(path), " = ", variableName, '.', elementName, ";\n")); >+ if (m_namedBindGroups[i].namedBindings[j].lengthInformation) { >+ auto& path = m_entryPointItems.inputs[iterator->value].path; >+ auto elementName = m_namedBindGroups[i].namedBindings[j].elementName; >+ auto lengthElementName = m_namedBindGroups[i].namedBindings[j].lengthInformation->elementName; >+ auto lengthTemporaryName = m_namedBindGroups[i].namedBindings[j].lengthInformation->temporaryName; >+ >+ auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType; >+ ASSERT(is<AST::ReferenceType>(unnamedType)); >+ auto& referenceType = downcast<AST::ReferenceType>(unnamedType); >+ auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType()); >+ >+ stringBuilder.append(makeString("size_t ", lengthTemporaryName, " = ", variableName, '.', lengthElementName, ".x;\n")); >+ stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " << 32;\n")); >+ stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " | ", variableName, '.', lengthElementName, ".y;\n")); >+ stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " / sizeof(", mangledTypeName, ");\n")); >+ stringBuilder.append(makeString("if (", lengthTemporaryName, " > 0xFFFFFFFF) ", lengthTemporaryName, " = 0xFFFFFFFF;\n")); >+ stringBuilder.append(makeString(mangledInputPath(path), " = { ", variableName, '.', elementName, ", static_cast<uint32_t>(", lengthTemporaryName, ") };\n")); >+ } else { >+ auto& path = m_entryPointItems.inputs[iterator->value].path; >+ auto elementName = m_namedBindGroups[i].namedBindings[j].elementName; >+ stringBuilder.append(makeString(mangledInputPath(path), " = ", variableName, '.', elementName, ";\n")); >+ } > } > } > > for (auto& namedBuiltIn : m_namedBuiltIns) { >- auto& path = m_entryPointItems.inputs[namedBuiltIn.indexInEntryPointItems].path; >+ auto& item = m_entryPointItems.inputs[namedBuiltIn.indexInEntryPointItems]; >+ auto& path = item.path; > auto& variableName = namedBuiltIn.variableName; >- stringBuilder.append(makeString(mangledInputPath(path), " = ", variableName, ";\n")); >+ auto mangledTypeName = m_typeNamer.mangledNameForType(*item.unnamedType); >+ stringBuilder.append(makeString(mangledInputPath(path), " = ", mangledTypeName, '(', variableName, ");\n")); > } > return stringBuilder.toString(); > } >@@ -289,8 +363,13 @@ VertexEntryPointScaffolding::VertexEntry > > m_namedOutputs.reserveInitialCapacity(m_entryPointItems.outputs.size()); > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { >+ auto& outputItem = m_entryPointItems.outputs[i]; > NamedOutput namedOutput; > namedOutput.elementName = m_typeNamer.generateNextStructureElementName(); >+ if (WTF::holds_alternative<AST::BuiltInSemantic>(*outputItem.semantic)) >+ namedOutput.internalTypeName = internalTypeForSemantic(WTF::get<AST::BuiltInSemantic>(*outputItem.semantic)); >+ if (namedOutput.internalTypeName.isNull()) >+ namedOutput.internalTypeName = m_typeNamer.mangledNameForType(*outputItem.unnamedType); > m_namedOutputs.uncheckedAppend(WTFMove(namedOutput)); > } > } >@@ -311,10 +390,10 @@ String VertexEntryPointScaffolding::help > stringBuilder.append(makeString("struct ", m_returnStructName, " {\n")); > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { > auto& outputItem = m_entryPointItems.outputs[i]; >- auto mangledTypeName = m_typeNamer.mangledNameForType(*outputItem.unnamedType); >+ auto& internalTypeName = m_namedOutputs[i].internalTypeName; > auto elementName = m_namedOutputs[i].elementName; > auto attribute = attributeForSemantic(*outputItem.semantic); >- stringBuilder.append(makeString(" ", mangledTypeName, ' ', elementName, ' ', attribute, ";\n")); >+ stringBuilder.append(makeString(" ", internalTypeName, ' ', elementName, ' ', attribute, ";\n")); > } > stringBuilder.append("};\n\n"); > >@@ -363,8 +442,9 @@ String VertexEntryPointScaffolding::pack > } > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { > auto& elementName = m_namedOutputs[i].elementName; >+ auto& internalTypeName = m_namedOutputs[i].internalTypeName; > auto& path = m_entryPointItems.outputs[i].path; >- stringBuilder.append(makeString(outputVariableName, '.', elementName, " = ", inputVariableName, mangledOutputPath(path), ";\n")); >+ stringBuilder.append(makeString(outputVariableName, '.', elementName, " = ", internalTypeName, '(', inputVariableName, mangledOutputPath(path), ");\n")); > } > return stringBuilder.toString(); > } >@@ -389,8 +469,13 @@ FragmentEntryPointScaffolding::FragmentE > > m_namedOutputs.reserveInitialCapacity(m_entryPointItems.outputs.size()); > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { >+ auto& outputItem = m_entryPointItems.outputs[i]; > NamedOutput namedOutput; > namedOutput.elementName = m_typeNamer.generateNextStructureElementName(); >+ if (WTF::holds_alternative<AST::BuiltInSemantic>(*outputItem.semantic)) >+ namedOutput.internalTypeName = internalTypeForSemantic(WTF::get<AST::BuiltInSemantic>(*outputItem.semantic)); >+ if (namedOutput.internalTypeName.isNull()) >+ namedOutput.internalTypeName = m_typeNamer.mangledNameForType(*outputItem.unnamedType); > m_namedOutputs.uncheckedAppend(WTFMove(namedOutput)); > } > } >@@ -411,10 +496,10 @@ String FragmentEntryPointScaffolding::he > stringBuilder.append(makeString("struct ", m_returnStructName, " {\n")); > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { > auto& outputItem = m_entryPointItems.outputs[i]; >- auto mangledTypeName = m_typeNamer.mangledNameForType(*outputItem.unnamedType); >+ auto& internalTypeName = m_namedOutputs[i].internalTypeName; > auto elementName = m_namedOutputs[i].elementName; > auto attribute = attributeForSemantic(*outputItem.semantic); >- stringBuilder.append(makeString(" ", mangledTypeName, ' ', elementName, ' ', attribute, ";\n")); >+ stringBuilder.append(makeString(" ", internalTypeName, ' ', elementName, ' ', attribute, ";\n")); > } > stringBuilder.append("};\n\n"); > >@@ -463,8 +548,9 @@ String FragmentEntryPointScaffolding::pa > } > for (size_t i = 0; i < m_entryPointItems.outputs.size(); ++i) { > auto& elementName = m_namedOutputs[i].elementName; >+ auto& internalTypeName = m_namedOutputs[i].internalTypeName; > auto& path = m_entryPointItems.outputs[i].path; >- stringBuilder.append(makeString(outputVariableName, '.', elementName, " = ", inputVariableName, mangledOutputPath(path), ";\n")); >+ stringBuilder.append(makeString(outputVariableName, '.', elementName, " = ", internalTypeName, '(', inputVariableName, mangledOutputPath(path), ");\n")); > } > return stringBuilder.toString(); > } >@@ -483,7 +569,7 @@ String ComputeEntryPointScaffolding::sig > { > StringBuilder stringBuilder; > >- stringBuilder.append(makeString("compute void ", functionName, '(')); >+ stringBuilder.append(makeString("kernel void ", functionName, '(')); > bool empty = true; > if (auto resourceSignature = this->resourceSignature()) { > empty = false; >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h (working copy) >@@ -77,9 +77,15 @@ protected: > Layout& m_layout; > std::function<String()> m_generateNextVariableName; > >+ struct LengthInformation { >+ String elementName; >+ String temporaryName; >+ unsigned index; >+ }; > struct NamedBinding { > String elementName; > unsigned index; >+ Optional<LengthInformation> lengthInformation; > }; > struct NamedBindGroup { > String structName; >@@ -123,6 +129,7 @@ private: > > struct NamedOutput { > String elementName; >+ String internalTypeName; > }; > Vector<NamedOutput> m_namedOutputs; > }; >@@ -151,6 +158,7 @@ private: > > struct NamedOutput { > String elementName; >+ String internalTypeName; > }; > Vector<NamedOutput> m_namedOutputs; > }; >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (working copy) >@@ -38,6 +38,8 @@ > #include <wtf/SetForScope.h> > #include <wtf/text/StringBuilder.h> > >+#include "WHLSLASTDumper.h" >+ > namespace WebCore { > > namespace WHLSL { >@@ -88,8 +90,18 @@ public: > , m_functionMapping(functionMapping) > , m_layout(layout) > { >+ m_stringBuilder.append(makeString( >+ "template <typename T>\n" >+ "inline void", memsetZeroFunctionName, "(T& value)\n" >+ "{\n" >+ " thread char* ptr = static_cast<thread char*>(static_cast<thread void*>(&value));\n" >+ " for (size_t i = 0; i < sizeof(T); ++i)\n" >+ " ptr[i] = 0;\n" >+ "}\n")); > } > >+ static constexpr const char* memsetZeroFunctionName = "memsetZero"; >+ > virtual ~FunctionDefinitionWriter() = default; > > String toString() { return m_stringBuilder.toString(); } >@@ -153,12 +165,42 @@ protected: > return makeString("variable", m_variableCount++); > } > >+ struct StackItem { >+ String value; >+ String leftValue; >+ }; >+ >+ void appendRightValue(AST::Expression& expression, String value) >+ { >+ UNUSED_PARAM(expression); >+ m_stack.append({ WTFMove(value), String() }); >+ } >+ >+ void appendLeftValue(AST::Expression& expression, String value, String leftValue) >+ { >+ RELEASE_ASSERT(expression.typeAnnotation().leftAddressSpace()); >+ m_stack.append({ WTFMove(value), WTFMove(leftValue) }); >+ } >+ >+ String takeLastValue() >+ { >+ RELEASE_ASSERT(m_stack.last().value); >+ return m_stack.takeLast().value; >+ } >+ >+ String takeLastLeftValue() >+ { >+ RELEASE_ASSERT(m_stack.last().leftValue); >+ return m_stack.takeLast().leftValue; >+ } >+ > Intrinsics& m_intrinsics; > TypeNamer& m_typeNamer; > HashMap<AST::FunctionDeclaration*, String>& m_functionMapping; > HashMap<AST::VariableDeclaration*, String> m_variableMapping; > StringBuilder m_stringBuilder; >- Vector<String> m_stack; >+ >+ Vector<StackItem> m_stack; > std::unique_ptr<EntryPointScaffolding> m_entryPointScaffolding; > Layout& m_layout; > unsigned m_variableCount { 0 }; >@@ -169,7 +211,7 @@ void FunctionDefinitionWriter::visit(AST > { > auto iterator = m_functionMapping.find(&nativeFunctionDeclaration); > ASSERT(iterator != m_functionMapping.end()); >- m_stringBuilder.append(writeNativeFunction(nativeFunctionDeclaration, iterator->value, m_intrinsics, m_typeNamer)); >+ m_stringBuilder.append(writeNativeFunction(nativeFunctionDeclaration, iterator->value, m_intrinsics, m_typeNamer, memsetZeroFunctionName)); > } > > void FunctionDefinitionWriter::visit(AST::FunctionDefinition& functionDefinition) >@@ -246,7 +288,7 @@ void FunctionDefinitionWriter::visit(AST > void FunctionDefinitionWriter::visit(AST::EffectfulExpressionStatement& effectfulExpressionStatement) > { > checkErrorAndVisit(effectfulExpressionStatement.effectfulExpression()); >- m_stack.takeLast(); // The statement is already effectful, so we don't need to do anything with the result. >+ takeLastValue(); // The statement is already effectful, so we don't need to do anything with the result. > } > > void FunctionDefinitionWriter::visit(AST::Fallthrough&) >@@ -264,7 +306,7 @@ void FunctionDefinitionWriter::emitLoop( > > if (loopConditionLocation == LoopConditionLocation::BeforeBody && conditionExpression) { > checkErrorAndVisit(*conditionExpression); >- m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >+ m_stringBuilder.append(makeString("if (!", takeLastValue(), ") break;\n")); > } > > m_stringBuilder.append("do {\n"); >@@ -276,12 +318,12 @@ void FunctionDefinitionWriter::emitLoop( > checkErrorAndVisit(*increment); > // Expression results get pushed to m_stack. We don't use the result > // of increment, so we dispense of that now. >- m_stack.takeLast(); >+ takeLastValue(); > } > > if (loopConditionLocation == LoopConditionLocation::AfterBody && conditionExpression) { > checkErrorAndVisit(*conditionExpression); >- m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >+ m_stringBuilder.append(makeString("if (!", takeLastValue(), ") break;\n")); > } > > m_stringBuilder.append("} \n"); >@@ -305,7 +347,7 @@ void FunctionDefinitionWriter::visit(AST > checkErrorAndVisit(statement); > }, [&](UniqueRef<AST::Expression>& expression) { > checkErrorAndVisit(expression); >- m_stack.takeLast(); // We don't need to do anything with the result. >+ takeLastValue(); // We don't need to do anything with the result. > }), forLoop.initialization()); > > emitLoop(LoopConditionLocation::BeforeBody, forLoop.condition(), forLoop.increment(), forLoop.body()); >@@ -315,7 +357,7 @@ void FunctionDefinitionWriter::visit(AST > void FunctionDefinitionWriter::visit(AST::IfStatement& ifStatement) > { > checkErrorAndVisit(ifStatement.conditional()); >- m_stringBuilder.append(makeString("if (", m_stack.takeLast(), ") {\n")); >+ m_stringBuilder.append(makeString("if (", takeLastValue(), ") {\n")); > checkErrorAndVisit(ifStatement.body()); > if (ifStatement.elseBody()) { > m_stringBuilder.append("} else {\n"); >@@ -330,10 +372,10 @@ void FunctionDefinitionWriter::visit(AST > checkErrorAndVisit(*returnStatement.value()); > if (m_entryPointScaffolding) { > auto variableName = generateNextVariableName(); >- m_stringBuilder.append(m_entryPointScaffolding->pack(m_stack.takeLast(), variableName)); >+ m_stringBuilder.append(m_entryPointScaffolding->pack(takeLastValue(), variableName)); > m_stringBuilder.append(makeString("return ", variableName, ";\n")); > } else >- m_stringBuilder.append(makeString("return ", m_stack.takeLast(), ";\n")); >+ m_stringBuilder.append(makeString("return ", takeLastValue(), ";\n")); > } else > m_stringBuilder.append("return;\n"); > } >@@ -342,7 +384,7 @@ void FunctionDefinitionWriter::visit(AST > { > checkErrorAndVisit(switchStatement.value()); > >- m_stringBuilder.append(makeString("switch (", m_stack.takeLast(), ") {")); >+ m_stringBuilder.append(makeString("switch (", takeLastValue(), ") {")); > for (auto& switchCase : switchStatement.switchCases()) > checkErrorAndVisit(switchCase); > m_stringBuilder.append("}\n"); >@@ -375,7 +417,7 @@ void FunctionDefinitionWriter::visit(AST > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(integerLiteral.resolvedType()); > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = static_cast<", mangledTypeName, ">(", integerLiteral.value(), ");\n")); >- m_stack.append(variableName); >+ appendRightValue(integerLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::UnsignedIntegerLiteral& unsignedIntegerLiteral) >@@ -383,7 +425,7 @@ void FunctionDefinitionWriter::visit(AST > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(unsignedIntegerLiteral.resolvedType()); > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = static_cast<", mangledTypeName, ">(", unsignedIntegerLiteral.value(), ");\n")); >- m_stack.append(variableName); >+ appendRightValue(unsignedIntegerLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::FloatLiteral& floatLiteral) >@@ -391,7 +433,7 @@ void FunctionDefinitionWriter::visit(AST > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(floatLiteral.resolvedType()); > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = static_cast<", mangledTypeName, ">(", floatLiteral.value(), ");\n")); >- m_stack.append(variableName); >+ appendRightValue(floatLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::NullLiteral& nullLiteral) >@@ -408,7 +450,7 @@ void FunctionDefinitionWriter::visit(AST > else > m_stringBuilder.append("nullptr"); > m_stringBuilder.append(";\n"); >- m_stack.append(variableName); >+ appendRightValue(nullLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::BooleanLiteral& booleanLiteral) >@@ -416,7 +458,7 @@ void FunctionDefinitionWriter::visit(AST > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(booleanLiteral.resolvedType()); > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = static_cast<", mangledTypeName, ">(", booleanLiteral.value() ? "true" : "false", ");\n")); >- m_stack.append(variableName); >+ appendRightValue(booleanLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral) >@@ -426,7 +468,7 @@ void FunctionDefinitionWriter::visit(AST > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(enumerationMemberLiteral.resolvedType()); > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = ", mangledTypeName, '.', m_typeNamer.mangledNameForEnumerationMember(*enumerationMemberLiteral.enumerationMember()), ";\n")); >- m_stack.append(variableName); >+ appendRightValue(enumerationMemberLiteral, variableName); > } > > void FunctionDefinitionWriter::visit(AST::Expression& expression) >@@ -434,37 +476,39 @@ void FunctionDefinitionWriter::visit(AST > Visitor::visit(expression); > } > >-void FunctionDefinitionWriter::visit(AST::DotExpression&) >+void FunctionDefinitionWriter::visit(AST::DotExpression& dotExpression) > { > // This should be lowered already. > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195788 Replace this with ASSERT_NOT_REACHED(). > notImplemented(); >- m_stack.append("dummy"); >+ appendRightValue(dotExpression, "dummy"); > } > > void FunctionDefinitionWriter::visit(AST::GlobalVariableReference& globalVariableReference) > { >- auto variableName = generateNextVariableName(); >+ auto valueName = generateNextVariableName(); >+ auto pointerName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(globalVariableReference.resolvedType()); > checkErrorAndVisit(globalVariableReference.base()); >- m_stringBuilder.append(makeString("thread ", mangledTypeName, "& ", variableName, " = ", m_stack.takeLast(), "->", m_typeNamer.mangledNameForStructureElement(globalVariableReference.structField()), ";\n")); >- m_stack.append(variableName); >+ m_stringBuilder.append(makeString("thread ", mangledTypeName, "* ", pointerName, " = &", takeLastValue(), "->", m_typeNamer.mangledNameForStructureElement(globalVariableReference.structField()), ";\n")); >+ m_stringBuilder.append(makeString(mangledTypeName, ' ', valueName, " = ", "*", pointerName, ";\n")); >+ appendLeftValue(globalVariableReference, valueName, pointerName); > } > >-void FunctionDefinitionWriter::visit(AST::IndexExpression&) >+void FunctionDefinitionWriter::visit(AST::IndexExpression& indexExpression) > { > // This should be lowered already. > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195788 Replace this with ASSERT_NOT_REACHED(). > notImplemented(); >- m_stack.append("dummy"); >+ appendRightValue(indexExpression, "dummy"); > } > >-void FunctionDefinitionWriter::visit(AST::PropertyAccessExpression&) >+void FunctionDefinitionWriter::visit(AST::PropertyAccessExpression& propertyAccessExpression) > { > // This should be lowered already. > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195788 Replace this with ASSERT_NOT_REACHED(). > notImplemented(); >- m_stack.append("dummy"); >+ appendRightValue(propertyAccessExpression, "dummy"); > } > > void FunctionDefinitionWriter::visit(AST::VariableDeclaration& variableDeclaration) >@@ -476,7 +520,7 @@ void FunctionDefinitionWriter::visit(AST > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198160 Implement qualifiers. > if (variableDeclaration.initializer()) { > checkErrorAndVisit(*variableDeclaration.initializer()); >- m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*variableDeclaration.type()), ' ', variableName, " = ", m_stack.takeLast(), ";\n")); >+ m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*variableDeclaration.type()), ' ', variableName, " = ", takeLastValue(), ";\n")); > } else > m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(*variableDeclaration.type()), ' ', variableName, ";\n")); > } >@@ -484,11 +528,12 @@ void FunctionDefinitionWriter::visit(AST > void FunctionDefinitionWriter::visit(AST::AssignmentExpression& assignmentExpression) > { > checkErrorAndVisit(assignmentExpression.left()); >- auto leftName = m_stack.takeLast(); >+ auto pointerName = takeLastLeftValue(); > checkErrorAndVisit(assignmentExpression.right()); >- auto rightName = m_stack.takeLast(); >- m_stringBuilder.append(makeString(leftName, " = ", rightName, ";\n")); >- m_stack.append(rightName); >+ auto rightName = takeLastValue(); >+ m_stringBuilder.append(makeString("if (", pointerName, ") *", pointerName, " = ", rightName, ";\n")); >+ //m_stringBuilder.append(makeString("*", pointerName, " = ", rightName, ";\n")); >+ appendRightValue(assignmentExpression, rightName); > } > > void FunctionDefinitionWriter::visit(AST::CallExpression& callExpression) >@@ -496,7 +541,7 @@ void FunctionDefinitionWriter::visit(AST > Vector<String> argumentNames; > for (auto& argument : callExpression.arguments()) { > checkErrorAndVisit(argument); >- argumentNames.append(m_stack.takeLast()); >+ argumentNames.append(takeLastValue()); > } > ASSERT(callExpression.function()); > auto iterator = m_functionMapping.find(callExpression.function()); >@@ -509,7 +554,7 @@ void FunctionDefinitionWriter::visit(AST > m_stringBuilder.append(argumentNames[i]); > } > m_stringBuilder.append(");\n"); >- m_stack.append(variableName); >+ appendRightValue(callExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::CommaExpression& commaExpression) >@@ -517,26 +562,30 @@ void FunctionDefinitionWriter::visit(AST > String result; > for (auto& expression : commaExpression.list()) { > checkErrorAndVisit(expression); >- result = m_stack.takeLast(); >+ result = takeLastValue(); > } >- m_stack.append(result); >+ appendRightValue(commaExpression, result); > } > > void FunctionDefinitionWriter::visit(AST::DereferenceExpression& dereferenceExpression) > { > checkErrorAndVisit(dereferenceExpression.pointer()); >- auto right = m_stack.takeLast(); >+ auto right = takeLastValue(); > auto variableName = generateNextVariableName(); >- m_stringBuilder.append(makeString(AST::toString(*dereferenceExpression.typeAnnotation().leftAddressSpace()), ' ', m_typeNamer.mangledNameForType(dereferenceExpression.resolvedType()), "& ", variableName, " = *", right, ";\n")); >- m_stack.append(variableName); >+ auto pointerName = generateNextVariableName(); >+ m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(dereferenceExpression.pointer().resolvedType()), ' ', pointerName, " = ", right, ";\n")); >+ m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(dereferenceExpression.resolvedType()), ' ', variableName, ";\n")); >+ m_stringBuilder.append(makeString("if (", pointerName, ") ", variableName, " = *", right, ";\n")); >+ m_stringBuilder.append(makeString("else ", memsetZeroFunctionName, '(', variableName, ");\n")); >+ appendLeftValue(dereferenceExpression, variableName, pointerName); > } > > void FunctionDefinitionWriter::visit(AST::LogicalExpression& logicalExpression) > { > checkErrorAndVisit(logicalExpression.left()); >- auto left = m_stack.takeLast(); >+ auto left = takeLastValue(); > checkErrorAndVisit(logicalExpression.right()); >- auto right = m_stack.takeLast(); >+ auto right = takeLastValue(); > auto variableName = generateNextVariableName(); > m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(logicalExpression.resolvedType()), ' ', variableName, " = ", left)); > switch (logicalExpression.type()) { >@@ -549,22 +598,22 @@ void FunctionDefinitionWriter::visit(AST > break; > } > m_stringBuilder.append(makeString(right, ";\n")); >- m_stack.append(variableName); >+ appendRightValue(logicalExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::LogicalNotExpression& logicalNotExpression) > { > checkErrorAndVisit(logicalNotExpression.operand()); >- auto operand = m_stack.takeLast(); >+ auto operand = takeLastValue(); > auto variableName = generateNextVariableName(); > m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(logicalNotExpression.resolvedType()), ' ', variableName, " = !", operand, ";\n")); >- m_stack.append(variableName); >+ appendRightValue(logicalNotExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpression) > { > checkErrorAndVisit(makeArrayReferenceExpression.leftValue()); >- auto lValue = m_stack.takeLast(); >+ auto lValue = takeLastValue(); > auto variableName = generateNextVariableName(); > auto mangledTypeName = m_typeNamer.mangledNameForType(makeArrayReferenceExpression.resolvedType()); > if (is<AST::PointerType>(makeArrayReferenceExpression.resolvedType())) >@@ -574,16 +623,16 @@ void FunctionDefinitionWriter::visit(AST > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = { &(", lValue, "[0]), ", arrayType.numElements(), " };\n")); > } else > m_stringBuilder.append(makeString(mangledTypeName, ' ', variableName, " = { &", lValue, ", 1 };\n")); >- m_stack.append(variableName); >+ appendRightValue(makeArrayReferenceExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::MakePointerExpression& makePointerExpression) > { > checkErrorAndVisit(makePointerExpression.leftValue()); >- auto lValue = m_stack.takeLast(); >+ auto pointer = takeLastLeftValue(); > auto variableName = generateNextVariableName(); >- m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(makePointerExpression.resolvedType()), ' ', variableName, " = &", lValue, ";\n")); >- m_stack.append(variableName); >+ m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(makePointerExpression.resolvedType()), ' ', variableName, " = ", pointer, ";\n")); >+ appendRightValue(makePointerExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::ReadModifyWriteExpression&) >@@ -595,27 +644,31 @@ void FunctionDefinitionWriter::visit(AST > void FunctionDefinitionWriter::visit(AST::TernaryExpression& ternaryExpression) > { > checkErrorAndVisit(ternaryExpression.predicate()); >- auto check = m_stack.takeLast(); >+ auto check = takeLastValue(); > > auto variableName = generateNextVariableName(); > m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(ternaryExpression.resolvedType()), ' ', variableName, ";\n")); > > m_stringBuilder.append(makeString("if (", check, ") {\n")); > checkErrorAndVisit(ternaryExpression.bodyExpression()); >- m_stringBuilder.append(makeString(variableName, " = ", m_stack.takeLast(), ";\n")); >+ m_stringBuilder.append(makeString(variableName, " = ", takeLastValue(), ";\n")); > m_stringBuilder.append("} else {\n"); > checkErrorAndVisit(ternaryExpression.elseExpression()); >- m_stringBuilder.append(makeString(variableName, " = ", m_stack.takeLast(), ";\n")); >+ m_stringBuilder.append(makeString(variableName, " = ", takeLastValue(), ";\n")); > m_stringBuilder.append("}\n"); >- m_stack.append(variableName); >+ appendRightValue(ternaryExpression, variableName); > } > > void FunctionDefinitionWriter::visit(AST::VariableReference& variableReference) > { > ASSERT(variableReference.variable()); >+ // FIXME: Are we always thread addr space here? https://bugs.webkit.org/show_bug.cgi?id=198166 >+ // OOPS > auto iterator = m_variableMapping.find(variableReference.variable()); > ASSERT(iterator != m_variableMapping.end()); >- m_stack.append(iterator->value); >+ auto pointerName = generateNextVariableName(); >+ m_stringBuilder.append(makeString("thread ", m_typeNamer.mangledNameForType(variableReference.resolvedType()), "* ", pointerName, " = &", iterator->value, ";\n")); >+ appendLeftValue(variableReference, iterator->value, pointerName); > } > > String FunctionDefinitionWriter::constantExpressionString(AST::ConstantExpression& constantExpression) >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp (working copy) >@@ -63,21 +63,6 @@ static String mapFunctionName(String& fu > return functionName; > } > >-static String convertAddressSpace(AST::AddressSpace addressSpace) >-{ >- switch (addressSpace) { >- case AST::AddressSpace::Constant: >- return "constant"_str; >- case AST::AddressSpace::Device: >- return "device"_str; >- case AST::AddressSpace::Threadgroup: >- return "threadgroup"_str; >- default: >- ASSERT(addressSpace == AST::AddressSpace::Thread); >- return "thread"_str; >- } >-} >- > static String atomicName(String input) > { > if (input == "Add") >@@ -96,7 +81,7 @@ static String atomicName(String input) > return "fetch_xor"_str; > } > >-String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclaration, String& outputFunctionName, Intrinsics& intrinsics, TypeNamer& typeNamer) >+String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclaration, String& outputFunctionName, Intrinsics& intrinsics, TypeNamer& typeNamer, const char* memsetZeroFunctionName) > { > StringBuilder stringBuilder; > if (nativeFunctionDeclaration.isCast()) { >@@ -104,8 +89,7 @@ String writeNativeFunction(AST::NativeFu > if (!nativeFunctionDeclaration.parameters().size()) { > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, "() {\n")); > stringBuilder.append(makeString(" ", metalReturnName, " x;\n")); >- stringBuilder.append(" thread char* ptr = static_cast<thread char*>(static_cast<thread void*>(&x));\n"); >- stringBuilder.append(makeString(" for (size_t i = 0; i < sizeof(", metalReturnName, "); ++i) ptr[i] = 0;\n")); >+ stringBuilder.append(makeString(" ", memsetZeroFunctionName, "(x);\n")); > stringBuilder.append(" return x;\n"); > stringBuilder.append("}\n"); > return stringBuilder.toString(); >@@ -246,9 +230,9 @@ String writeNativeFunction(AST::NativeFu > auto metalParameter1Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[0]->type()); > auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type()); > auto metalReturnName = typeNamer.mangledNameForType(nativeFunctionDeclaration.type()); >- auto fieldName = nativeFunctionDeclaration.name().substring("operator&[]."_str.length()); > stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " v, ", metalParameter2Name, " n) {\n")); >- stringBuilder.append(makeString(" return &(v.pointer[n]);\n")); >+ stringBuilder.append(" if (n < v.length) return &(v.pointer[n]);\n"); >+ stringBuilder.append(" return nullptr;\n"); > stringBuilder.append("}\n"); > return stringBuilder.toString(); > } >@@ -376,7 +360,7 @@ String writeNativeFunction(AST::NativeFu > auto& fourthArgumentPointer = downcast<AST::PointerType>(*nativeFunctionDeclaration.parameters()[3]->type()); > auto fourthArgumentAddressSpace = fourthArgumentPointer.addressSpace(); > auto fourthArgumentPointee = typeNamer.mangledNameForType(fourthArgumentPointer.elementType()); >- stringBuilder.append(makeString("void ", outputFunctionName, '(', convertAddressSpace(firstArgumentAddressSpace), ' ', firstArgumentPointee, "* object, ", secondArgument, " compare, ", thirdArgument, " desired, ", convertAddressSpace(fourthArgumentAddressSpace), ' ', fourthArgumentPointee, "* out) {\n")); >+ stringBuilder.append(makeString("void ", outputFunctionName, '(', toString(firstArgumentAddressSpace), ' ', firstArgumentPointee, "* object, ", secondArgument, " compare, ", thirdArgument, " desired, ", toString(fourthArgumentAddressSpace), ' ', fourthArgumentPointee, "* out) {\n")); > stringBuilder.append(" atomic_compare_exchange_weak_explicit(object, &compare, desired, memory_order_relaxed);\n"); > stringBuilder.append(" *out = compare;\n"); > stringBuilder.append("}\n"); >@@ -394,7 +378,7 @@ String writeNativeFunction(AST::NativeFu > auto thirdArgumentAddressSpace = thirdArgumentPointer.addressSpace(); > auto thirdArgumentPointee = typeNamer.mangledNameForType(thirdArgumentPointer.elementType()); > auto name = atomicName(nativeFunctionDeclaration.name().substring("Interlocked"_str.length())); >- stringBuilder.append(makeString("void ", outputFunctionName, '(', convertAddressSpace(firstArgumentAddressSpace), ' ', firstArgumentPointee, "* object, ", secondArgument, " operand, ", convertAddressSpace(thirdArgumentAddressSpace), ' ', thirdArgumentPointee, "* out) {\n")); >+ stringBuilder.append(makeString("void ", outputFunctionName, '(', toString(firstArgumentAddressSpace), ' ', firstArgumentPointee, "* object, ", secondArgument, " operand, ", toString(thirdArgumentAddressSpace), ' ', thirdArgumentPointee, "* out) {\n")); > stringBuilder.append(makeString(" *out = atomic_fetch_", name, "_explicit(object, operand, memory_order_relaxed);\n")); > stringBuilder.append("}\n"); > return stringBuilder.toString(); >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.h (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.h (working copy) >@@ -45,7 +45,7 @@ namespace Metal { > > class TypeNamer; > >-String writeNativeFunction(AST::NativeFunctionDeclaration&, String& outputFunctionName, Intrinsics&, TypeNamer&); >+String writeNativeFunction(AST::NativeFunctionDeclaration&, String& outputFunctionName, Intrinsics&, TypeNamer&, const char* memsetZeroFunctionName); > > } > >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp (revision 246326) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp (working copy) >@@ -396,7 +396,7 @@ void TypeNamer::emitUnnamedTypeDefinitio > ASSERT(baseTypeNameNode.parent()); > stringBuilder.append(makeString("struct ", arrayReferenceType.mangledName(), "{ \n")); > stringBuilder.append(makeString(" ", toString(arrayReferenceType.addressSpace()), " ", arrayReferenceType.parent()->mangledName(), "* pointer;\n")); >- stringBuilder.append(" uint length;\n"); >+ stringBuilder.append(" uint32_t length;\n"); > stringBuilder.append("};\n"); > } else { > ASSERT(is<ArrayTypeNameNode>(baseTypeNameNode)); >Index: Source/WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- Source/WebCore/WebCore.xcodeproj/project.pbxproj (revision 246326) >+++ Source/WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -6394,6 +6394,10 @@ > 1C840B9921EC400800D0500D /* WHLSLGatherEntryPointItems.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLGatherEntryPointItems.cpp; sourceTree = "<group>"; }; > 1C840B9A21EC400900D0500D /* WHLSLGatherEntryPointItems.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLGatherEntryPointItems.h; sourceTree = "<group>"; }; > 1C840B9B21EC400900D0500D /* WHLSLChecker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLChecker.cpp; sourceTree = "<group>"; }; >+ 1C86CA4B22AA19FF001BF961 /* WHLSLComputeDimensions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLComputeDimensions.cpp; sourceTree = "<group>"; }; >+ 1C86CA4C22AA19FF001BF961 /* WHLSLComputeDimensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLComputeDimensions.h; sourceTree = "<group>"; }; >+ 1C86CA4E22AA23C9001BF961 /* GPUPipelineMetalConvertLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUPipelineMetalConvertLayout.cpp; sourceTree = "<group>"; }; >+ 1C86CA4F22AA23C9001BF961 /* GPUPipelineMetalConvertLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUPipelineMetalConvertLayout.h; sourceTree = "<group>"; }; > 1C904DF90BA9D2C80081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; }; > 1C9AE5CA21ED9DF50069D5F2 /* WHLSLHighZombieFinder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLHighZombieFinder.cpp; sourceTree = "<group>"; }; > 1C9AE5CB21ED9DF50069D5F2 /* WHLSLHighZombieFinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLHighZombieFinder.h; sourceTree = "<group>"; }; >@@ -25448,6 +25452,8 @@ > C234A9AE21E92C1A003C984D /* WHLSLCheckDuplicateFunctions.h */, > 1C840B9B21EC400900D0500D /* WHLSLChecker.cpp */, > 1C840B9721EC400700D0500D /* WHLSLChecker.h */, >+ 1C86CA4B22AA19FF001BF961 /* WHLSLComputeDimensions.cpp */, >+ 1C86CA4C22AA19FF001BF961 /* WHLSLComputeDimensions.h */, > 1CA0C2E421EED12A00A11860 /* WHLSLFunctionStageChecker.cpp */, > 1CA0C2E521EED12A00A11860 /* WHLSLFunctionStageChecker.h */, > 1C840B9921EC400800D0500D /* WHLSLGatherEntryPointItems.cpp */, >@@ -25987,6 +25993,8 @@ > D08903402241CE4600F3F440 /* GPUComputePassEncoderMetal.mm */, > D089033B224179B500F3F440 /* GPUComputePipelineMetal.mm */, > D087CE3C21ACA94200BDE174 /* GPUDeviceMetal.mm */, >+ 1C86CA4E22AA23C9001BF961 /* GPUPipelineMetalConvertLayout.cpp */, >+ 1C86CA4F22AA23C9001BF961 /* GPUPipelineMetalConvertLayout.h */, > D087CE3B21ACA94200BDE174 /* GPUProgrammablePassEncoderMetal.mm */, > D087CE3921ACA94200BDE174 /* GPUQueueMetal.mm */, > D087CE3A21ACA94200BDE174 /* GPURenderPassEncoderMetal.mm */, >Index: Source/WebCore/platform/graphics/gpu/GPUBindGroupLayout.h >=================================================================== >--- Source/WebCore/platform/graphics/gpu/GPUBindGroupLayout.h (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/GPUBindGroupLayout.h (working copy) >@@ -33,6 +33,7 @@ > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> > #include <wtf/RetainPtr.h> >+#include <wtf/Variant.h> > > #if USE(METAL) > OBJC_PROTOCOL(MTLArgumentEncoder); >@@ -47,7 +48,37 @@ class GPUBindGroupLayout : public RefCou > public: > static RefPtr<GPUBindGroupLayout> tryCreate(const GPUDevice&, const GPUBindGroupLayoutDescriptor&); > >- using BindingsMapType = HashMap<uint64_t, GPUBindGroupLayoutBinding, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>; >+ struct UniformBuffer { >+ unsigned internalLengthName; >+ }; >+ >+ struct DynamicUniformBuffer { >+ unsigned internalLengthName; >+ }; >+ >+ struct Sampler { >+ }; >+ >+ struct SampledTexture { >+ }; >+ >+ struct StorageBuffer { >+ unsigned internalLengthName; >+ }; >+ >+ struct DynamicStorageBuffer { >+ unsigned internalLengthName; >+ }; >+ >+ using InternalBindingDetails = Variant<UniformBuffer, DynamicUniformBuffer, Sampler, SampledTexture, StorageBuffer, DynamicStorageBuffer>; >+ >+ struct Binding { >+ GPUBindGroupLayoutBinding externalBinding; >+ unsigned internalName; >+ InternalBindingDetails internalBindingDetails; >+ }; >+ >+ using BindingsMapType = HashMap<uint64_t, Binding, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>; > const BindingsMapType& bindingsMap() const { return m_bindingsMap; } > #if USE(METAL) > MTLArgumentEncoder *vertexEncoder() const { return m_vertexEncoder.get(); } >Index: Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h >=================================================================== >--- Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/GPUComputePipeline.h (working copy) >@@ -27,6 +27,7 @@ > > #if ENABLE(WEBGPU) > >+#include "WHLSLPrepare.h" > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> > #include <wtf/RetainPtr.h> >@@ -48,10 +49,13 @@ public: > > const PlatformComputePipeline* platformComputePipeline() const { return m_platformComputePipeline.get(); } > >+ WHLSL::ComputeDimensions computeDimensions() const { return m_computeDimensions; } >+ > private: >- GPUComputePipeline(PlatformComputePipelineSmartPtr&&); >+ GPUComputePipeline(PlatformComputePipelineSmartPtr&&, WHLSL::ComputeDimensions); > > PlatformComputePipelineSmartPtr m_platformComputePipeline; >+ WHLSL::ComputeDimensions m_computeDimensions { 0, 0, 0 }; > }; > > } // namespace WebCore >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm (working copy) >@@ -77,6 +77,18 @@ static RetainPtr<MTLArgumentEncoder> try > return encoder; > }; > >+static RetainPtr<MTLArgumentDescriptor> argumentDescriptor(MTLDataType dataType, NSUInteger index) >+{ >+ RetainPtr<MTLArgumentDescriptor> mtlArgument; >+ BEGIN_BLOCK_OBJC_EXCEPTIONS; >+ mtlArgument = adoptNS([MTLArgumentDescriptor new]); >+ END_BLOCK_OBJC_EXCEPTIONS; >+ >+ [mtlArgument setDataType:dataType]; >+ [mtlArgument setIndex:index]; >+ return mtlArgument; >+} >+ > RefPtr<GPUBindGroupLayout> GPUBindGroupLayout::tryCreate(const GPUDevice& device, const GPUBindGroupLayoutDescriptor& descriptor) > { > if (!device.platformDevice()) { >@@ -87,48 +99,73 @@ RefPtr<GPUBindGroupLayout> GPUBindGroupL > ArgumentArray vertexArgsArray, fragmentArgsArray, computeArgsArray; > BindingsMapType bindingsMap; > >+ unsigned internalName = 0; >+ unsigned internalLengthBase = descriptor.bindings.size(); > for (const auto& binding : descriptor.bindings) { >- if (!bindingsMap.add(binding.binding, binding)) { >+ Optional<unsigned> extraIndex; >+ auto internalDetails = ([&]() -> GPUBindGroupLayout::InternalBindingDetails { >+ switch (binding.type) { >+ case GPUBindingType::UniformBuffer: >+ extraIndex = internalLengthBase++; >+ return GPUBindGroupLayout::UniformBuffer { *extraIndex }; >+ case GPUBindingType::DynamicUniformBuffer: >+ extraIndex = internalLengthBase++; >+ return GPUBindGroupLayout::DynamicUniformBuffer { *extraIndex }; >+ case GPUBindingType::Sampler: >+ return GPUBindGroupLayout::Sampler { }; >+ case GPUBindingType::SampledTexture: >+ return GPUBindGroupLayout::SampledTexture { }; >+ case GPUBindingType::StorageBuffer: >+ extraIndex = internalLengthBase++; >+ return GPUBindGroupLayout::StorageBuffer { *extraIndex }; >+ default: >+ ASSERT(binding.type == GPUBindingType::DynamicStorageBuffer); >+ extraIndex = internalLengthBase++; >+ return GPUBindGroupLayout::DynamicStorageBuffer { *extraIndex }; >+ } >+ })(); >+ Binding bindingDetails = { binding, internalName++, WTFMove(internalDetails) }; >+ if (!bindingsMap.add(binding.binding, bindingDetails)) { > LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Duplicate binding %u found in GPUBindGroupLayoutDescriptor!", binding.binding); > return nullptr; > } > >- RetainPtr<MTLArgumentDescriptor> mtlArgument; >+ RetainPtr<MTLArgumentDescriptor> mtlArgument = argumentDescriptor(MTLDataTypeForBindingType(binding.type), bindingDetails.internalName); > >- BEGIN_BLOCK_OBJC_EXCEPTIONS; >- mtlArgument = adoptNS([MTLArgumentDescriptor new]); >- END_BLOCK_OBJC_EXCEPTIONS; > if (!mtlArgument) { > LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Unable to create MTLArgumentDescriptor for binding %u!", binding.binding); > return nullptr; > } > >- [mtlArgument setDataType:MTLDataTypeForBindingType(binding.type)]; >- [mtlArgument setIndex:binding.binding]; >- >- if (binding.visibility & GPUShaderStageBit::Flags::Vertex) >- appendArgumentToArray(vertexArgsArray, mtlArgument); >- if (binding.visibility & GPUShaderStageBit::Flags::Fragment) >- appendArgumentToArray(fragmentArgsArray, mtlArgument); >- if (binding.visibility & GPUShaderStageBit::Flags::Compute) >- appendArgumentToArray(computeArgsArray, mtlArgument); >- } >- >- RetainPtr<MTLArgumentEncoder> vertex, fragment, compute; >- >- if (vertexArgsArray) { >- if (!(vertex = tryCreateMtlArgumentEncoder(device, vertexArgsArray))) >+ auto addIndices = [&](ArgumentArray& array) -> bool { >+ appendArgumentToArray(array, mtlArgument); >+ if (extraIndex) { >+ RetainPtr<MTLArgumentDescriptor> mtlArgument = argumentDescriptor(MTLDataTypeUInt2, *extraIndex); >+ if (!mtlArgument) { >+ LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Unable to create MTLArgumentDescriptor for binding %u!", binding.binding); >+ return false; >+ } >+ appendArgumentToArray(array, mtlArgument); >+ } >+ return true; >+ }; >+ if ((binding.visibility & GPUShaderStageBit::Flags::Vertex) && !addIndices(vertexArgsArray)) > return nullptr; >- } >- if (fragmentArgsArray) { >- if (!(fragment = tryCreateMtlArgumentEncoder(device, fragmentArgsArray))) >+ if ((binding.visibility & GPUShaderStageBit::Flags::Fragment) && !addIndices(fragmentArgsArray)) > return nullptr; >- } >- if (computeArgsArray) { >- if (!(compute = tryCreateMtlArgumentEncoder(device, computeArgsArray))) >+ if ((binding.visibility & GPUShaderStageBit::Flags::Compute) && !addIndices(computeArgsArray)) > return nullptr; > } > >+ RetainPtr<MTLArgumentEncoder> vertex, fragment, compute; >+ >+ if (vertexArgsArray && !(vertex = tryCreateMtlArgumentEncoder(device, vertexArgsArray))) >+ return nullptr; >+ if (fragmentArgsArray && !(fragment = tryCreateMtlArgumentEncoder(device, fragmentArgsArray))) >+ return nullptr; >+ if (computeArgsArray && !(compute = tryCreateMtlArgumentEncoder(device, computeArgsArray))) >+ return nullptr; >+ > return adoptRef(new GPUBindGroupLayout(WTFMove(bindingsMap), WTFMove(vertex), WTFMove(fragment), WTFMove(compute))); > } > >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm (working copy) >@@ -72,13 +72,15 @@ static Optional<GPUBufferBinding> tryGet > return GPUBufferBinding { bufferBinding.buffer.copyRef(), bufferBinding.offset, bufferBinding.size }; > } > >-static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned index) >+static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned name, unsigned lengthName) > { > ASSERT(argumentEncoder && bufferBinding.buffer->platformBuffer()); > > BEGIN_BLOCK_OBJC_EXCEPTIONS; > // Bounds check when converting GPUBufferBinding ensures that NSUInteger cast of uint64_t offset is safe. >- [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:static_cast<NSUInteger>(bufferBinding.offset) atIndex:index]; >+ [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:static_cast<NSUInteger>(bufferBinding.offset) atIndex:name]; >+ void* lengthPointer = [argumentEncoder constantDataAtIndex:lengthName]; >+ memcpy(lengthPointer, &bufferBinding.size, sizeof(uint64_t)); > END_BLOCK_OBJC_EXCEPTIONS; > } > >@@ -171,12 +173,12 @@ RefPtr<GPUBindGroup> GPUBindGroup::tryCr > return nullptr; > } > auto layoutBinding = layoutIterator->value; >- if (layoutBinding.visibility == GPUShaderStageBit::Flags::None) >+ if (layoutBinding.externalBinding.visibility == GPUShaderStageBit::Flags::None) > continue; > >- bool isForVertex = layoutBinding.visibility & GPUShaderStageBit::Flags::Vertex; >- bool isForFragment = layoutBinding.visibility & GPUShaderStageBit::Flags::Fragment; >- bool isForCompute = layoutBinding.visibility & GPUShaderStageBit::Flags::Compute; >+ bool isForVertex = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Vertex; >+ bool isForFragment = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Fragment; >+ bool isForCompute = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Compute; > > if (isForVertex && !vertexEncoder) { > LOG(WebGPU, "%s: No vertex argument encoder found for binding %u!", functionName, index); >@@ -191,39 +193,39 @@ RefPtr<GPUBindGroup> GPUBindGroup::tryCr > return nullptr; > } > >- switch (layoutBinding.type) { >- // FIXME: Support more resource types. >- // FIXME: We could avoid this ugly switch-on-type using virtual functions if GPUBindingResource is refactored as a base class rather than a Variant. >- case GPUBindingType::UniformBuffer: >- case GPUBindingType::StorageBuffer: { >+ auto handleBuffer = [&](unsigned internalLengthName) -> bool { > auto bufferResource = tryGetResourceAsBufferBinding(resourceBinding.resource, functionName); > if (!bufferResource) >- return nullptr; >+ return false; > if (isForVertex) >- setBufferOnEncoder(vertexEncoder, *bufferResource, index); >+ setBufferOnEncoder(vertexEncoder, *bufferResource, layoutBinding.internalName, internalLengthName); > if (isForFragment) >- setBufferOnEncoder(fragmentEncoder, *bufferResource, index); >+ setBufferOnEncoder(fragmentEncoder, *bufferResource, layoutBinding.internalName, internalLengthName); > if (isForCompute) >- setBufferOnEncoder(computeEncoder, *bufferResource, index); >+ setBufferOnEncoder(computeEncoder, *bufferResource, layoutBinding.internalName, internalLengthName); > boundBuffers.append(bufferResource->buffer.copyRef()); >- break; >- } >- case GPUBindingType::Sampler: { >+ return true; >+ }; >+ >+ auto success = WTF::visit(WTF::makeVisitor([&](GPUBindGroupLayout::UniformBuffer& uniformBuffer) -> bool { >+ return handleBuffer(uniformBuffer.internalLengthName); >+ }, [&](GPUBindGroupLayout::DynamicUniformBuffer& dynamicUniformBuffer) -> bool { >+ return handleBuffer(dynamicUniformBuffer.internalLengthName); >+ }, [&](GPUBindGroupLayout::Sampler&) -> bool { > auto samplerState = tryGetResourceAsMtlSampler(resourceBinding.resource, functionName); > if (!samplerState) >- return nullptr; >+ return false; > if (isForVertex) > setSamplerOnEncoder(vertexEncoder, samplerState, index); > if (isForFragment) > setSamplerOnEncoder(fragmentEncoder, samplerState, index); > if (isForCompute) > setSamplerOnEncoder(computeEncoder, samplerState, index); >- break; >- } >- case GPUBindingType::SampledTexture: { >+ return true; >+ }, [&](GPUBindGroupLayout::SampledTexture&) -> bool { > auto textureResource = tryGetResourceAsTexture(resourceBinding.resource, functionName); > if (!textureResource) >- return nullptr; >+ return false; > if (isForVertex) > setTextureOnEncoder(vertexEncoder, textureResource->platformTexture(), index); > if (isForFragment) >@@ -231,12 +233,14 @@ RefPtr<GPUBindGroup> GPUBindGroup::tryCr > if (isForCompute) > setTextureOnEncoder(computeEncoder, textureResource->platformTexture(), index); > boundTextures.append(textureResource.releaseNonNull()); >- break; >- } >- default: >- LOG(WebGPU, "%s: Resource type not yet implemented.", functionName); >+ return true; >+ }, [&](GPUBindGroupLayout::StorageBuffer& storageBuffer) -> bool { >+ return handleBuffer(storageBuffer.internalLengthName); >+ }, [&](GPUBindGroupLayout::DynamicStorageBuffer& dynamicStorageBuffer) -> bool { >+ return handleBuffer(dynamicStorageBuffer.internalLengthName); >+ }), layoutBinding.internalBindingDetails); >+ if (!success) > return nullptr; >- } > } > > return adoptRef(new GPUBindGroup(WTFMove(vertexArgsBuffer), WTFMove(fragmentArgsBuffer), WTFMove(computeArgsBuffer), WTFMove(boundBuffers), WTFMove(boundTextures))); >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePassEncoderMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePassEncoderMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePassEncoderMetal.mm (working copy) >@@ -92,16 +92,11 @@ void GPUComputePassEncoder::dispatch(uns > return; > } > >- auto pipelineState = m_pipeline->platformComputePipeline(); >- ASSERT(pipelineState); >+ ASSERT(m_pipeline->platformComputePipeline()); > > BEGIN_BLOCK_OBJC_EXCEPTIONS; > >- auto w = pipelineState.threadExecutionWidth; >- auto h = pipelineState.maxTotalThreadsPerThreadgroup / w; >- >- // FIXME: This should be gleaned from the shader if not using MSL. For now, use the docs' example calculation. >- auto threadsPerThreadgroup = MTLSizeMake(w, h, 1); >+ auto threadsPerThreadgroup = MTLSizeMake(m_pipeline->computeDimensions().width, m_pipeline->computeDimensions().height, m_pipeline->computeDimensions().depth); > > auto threadgroupsPerGrid = MTLSizeMake(x, y, z); > >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUComputePipelineMetal.mm (working copy) >@@ -30,68 +30,172 @@ > > #import "GPUComputePipelineDescriptor.h" > #import "GPUDevice.h" >+#import "GPUPipelineMetalConvertLayout.h" > #import "Logging.h" >+#import "WHLSLPrepare.h" > #import <Metal/Metal.h> > #import <wtf/BlockObjCExceptions.h> > >-OBJC_PROTOCOL(MTLFunction); >- > namespace WebCore { > >-static RetainPtr<MTLFunction> tryCreateMtlComputeFunction(const GPUPipelineStageDescriptor& stage) >+static bool trySetMetalFunctions(const char* const functionName, MTLLibrary *computeMetalLibrary, MTLComputePipelineDescriptor *mtlDescriptor, const String& computeEntryPointName) > { >- if (!stage.module->platformShaderModule() || stage.entryPoint.isNull()) { >- LOG(WebGPU, "GPUComputePipeline::tryCreate(): Invalid GPUShaderModule!"); >- return nullptr; >+#if LOG_DISABLED >+ UNUSED_PARAM(functionName); >+#endif >+ >+ BEGIN_BLOCK_OBJC_EXCEPTIONS; >+ >+ if (!computeMetalLibrary) { >+ LOG(WebGPU, "%s: MTLLibrary for compute stage does not exist!", functionName); >+ return false; > } > >- RetainPtr<MTLFunction> function; >+ auto function = adoptNS([computeMetalLibrary newFunctionWithName:computeEntryPointName]); >+ if (!function) { >+ LOG(WebGPU, "%s: Cannot create compute MTLFunction \"%s\"!", functionName, computeEntryPointName.utf8().data()); >+ return false; >+ } >+ >+ [mtlDescriptor setComputeFunction:function.get()]; >+ return true; >+ >+ END_BLOCK_OBJC_EXCEPTIONS; >+ >+ return false; >+} >+ >+static Optional<WHLSL::ComputeDimensions> trySetFunctions(const char* const functionName, const GPUPipelineStageDescriptor& computeStage, const GPUDevice& device, MTLComputePipelineDescriptor* mtlDescriptor, Optional<WHLSL::ComputePipelineDescriptor>& whlslDescriptor) >+{ >+#if LOG_DISABLED >+ UNUSED_PARAM(functionName); >+#endif >+ RetainPtr<MTLLibrary> computeLibrary; >+ String computeEntryPoint; >+ >+ WHLSL::ComputeDimensions computeDimensions { 1, 1, 1 }; >+ >+ if (whlslDescriptor) { >+ // WHLSL functions are compiled to MSL first. >+ String whlslSource = computeStage.module->whlslSource(); >+ ASSERT(!whlslSource.isNull()); >+ >+ whlslDescriptor->entryPointName = computeStage.entryPoint; >+ >+ auto whlslCompileResult = WHLSL::prepare(whlslSource, *whlslDescriptor); >+ if (!whlslCompileResult) >+ return WTF::nullopt; >+ computeDimensions = whlslCompileResult->computeDimensions; >+ >+ NSError *error = nil; >+ >+ BEGIN_BLOCK_OBJC_EXCEPTIONS; >+ computeLibrary = adoptNS([device.platformDevice() newLibraryWithSource:whlslCompileResult->metalSource options:nil error:&error]); >+ END_BLOCK_OBJC_EXCEPTIONS; >+ >+ ASSERT(computeLibrary); >+ // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195771 Once we zero-fill variables, there should be no warnings, so we should be able to ASSERT(!error) here. >+ >+ computeEntryPoint = whlslCompileResult->mangledEntryPointName; >+ } else { >+ computeLibrary = computeStage.module->platformShaderModule(); >+ computeEntryPoint = computeStage.entryPoint; >+ } >+ >+ if (trySetMetalFunctions(functionName, computeLibrary.get(), mtlDescriptor, computeEntryPoint)) >+ return computeDimensions; >+ return WTF::nullopt; >+} >+ >+struct ConvertResult { >+ RetainPtr<MTLComputePipelineDescriptor> pipelineDescriptor; >+ WHLSL::ComputeDimensions computeDimensions; >+}; >+static Optional<ConvertResult> convertComputePipelineDescriptor(const char* const functionName, const GPUComputePipelineDescriptor& descriptor, const GPUDevice& device) >+{ >+ RetainPtr<MTLComputePipelineDescriptor> mtlDescriptor; > > BEGIN_BLOCK_OBJC_EXCEPTIONS; >- function = adoptNS([stage.module->platformShaderModule() newFunctionWithName:stage.entryPoint]); >+ >+ mtlDescriptor = adoptNS([MTLComputePipelineDescriptor new]); >+ > END_BLOCK_OBJC_EXCEPTIONS; > >- if (!function) >- LOG(WebGPU, "GPUComputePipeline::tryCreate(): Cannot create compute MTLFunction \"%s\"!", stage.entryPoint.utf8().data()); >+ if (!mtlDescriptor) { >+ LOG(WebGPU, "%s: Error creating MTLDescriptor!", functionName); >+ return WTF::nullopt; >+ } >+ >+ const auto& computeStage = descriptor.computeStage; > >- return function; >+ bool isWhlsl = !computeStage.module->whlslSource().isNull(); >+ >+ Optional<WHLSL::ComputePipelineDescriptor> whlslDescriptor; >+ if (isWhlsl) >+ whlslDescriptor = WHLSL::ComputePipelineDescriptor(); >+ >+ if (descriptor.layout && whlslDescriptor) { >+ if (auto layout = convertLayout(*descriptor.layout)) >+ whlslDescriptor->layout = WTFMove(*layout); >+ else { >+ LOG(WebGPU, "%s: Error converting GPUPipelineLayout!", functionName); >+ return WTF::nullopt; >+ } >+ } >+ >+ if (auto computeDimensions = trySetFunctions(functionName, computeStage, device, mtlDescriptor.get(), whlslDescriptor)) >+ return {{ mtlDescriptor, *computeDimensions }}; >+ >+ return WTF::nullopt; > } > >-static RetainPtr<MTLComputePipelineState> tryCreateMTLComputePipelineState(const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor) >+struct CreateResult { >+ RetainPtr<MTLComputePipelineState> pipelineState; >+ WHLSL::ComputeDimensions computeDimensions; >+}; >+static Optional<CreateResult> tryCreateMTLComputePipelineState(const char* const functionName, const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor) > { > if (!device.platformDevice()) { > LOG(WebGPU, "GPUComputePipeline::tryCreate(): Invalid GPUDevice!"); >- return nullptr; >+ return WTF::nullopt; > } > >- auto computeFunction = tryCreateMtlComputeFunction(descriptor.computeStage); >- if (!computeFunction) >- return nullptr; >+ auto convertResult = convertComputePipelineDescriptor(functionName, descriptor, device); >+ if (!convertResult) >+ return WTF::nullopt; >+ ASSERT(convertResult->pipelineDescriptor); >+ auto mtlDescriptor = convertResult->pipelineDescriptor; > >- RetainPtr<MTLComputePipelineState> pipelineState; >- NSError *error = nil; >+ RetainPtr<MTLComputePipelineState> pipeline; > > BEGIN_BLOCK_OBJC_EXCEPTIONS; >- pipelineState = adoptNS([device.platformDevice() newComputePipelineStateWithFunction:computeFunction.get() error:&error]); >- END_BLOCK_OBJC_EXCEPTIONS; > >- if (!pipelineState) >+ NSError *error = nil; >+ pipeline = adoptNS([device.platformDevice() newComputePipelineStateWithDescriptor:mtlDescriptor.get() options:MTLPipelineOptionNone reflection:nil error:&error]); >+ if (!pipeline) { > LOG(WebGPU, "GPUComputePipeline::tryCreate(): %s!", error ? error.localizedDescription.UTF8String : "Unable to create MTLComputePipelineState!"); >+ return WTF::nullopt; >+ } >+ >+ END_BLOCK_OBJC_EXCEPTIONS; > >- return pipelineState; >+ return {{ pipeline, convertResult->computeDimensions }}; > } > > RefPtr<GPUComputePipeline> GPUComputePipeline::tryCreate(const GPUDevice& device, const GPUComputePipelineDescriptor& descriptor) > { >- auto mtlPipeline = tryCreateMTLComputePipelineState(device, descriptor); >- if (!mtlPipeline) >+ const char* const functionName = "GPURenderPipeline::create()"; >+ >+ auto createResult = tryCreateMTLComputePipelineState(functionName, device, descriptor); >+ if (!createResult) > return nullptr; > >- return adoptRef(new GPUComputePipeline(WTFMove(mtlPipeline))); >+ return adoptRef(new GPUComputePipeline(WTFMove(createResult->pipelineState), createResult->computeDimensions)); > } > >-GPUComputePipeline::GPUComputePipeline(RetainPtr<MTLComputePipelineState>&& pipeline) >+GPUComputePipeline::GPUComputePipeline(RetainPtr<MTLComputePipelineState>&& pipeline, WHLSL::ComputeDimensions computeDimensions) > : m_platformComputePipeline(WTFMove(pipeline)) >+ , m_computeDimensions(computeDimensions) > { > } > >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.cpp >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.cpp (nonexistent) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.cpp (working copy) >@@ -0,0 +1,94 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "GPUPipelineMetalConvertLayout.h" >+ >+#include "GPUPipelineLayout.h" >+ >+#if ENABLE(WEBGPU) >+ >+namespace WebCore { >+ >+static OptionSet<WHLSL::ShaderStage> convertShaderStageFlags(GPUShaderStageFlags flags) >+{ >+ OptionSet<WHLSL::ShaderStage> result; >+ if (flags & GPUShaderStageBit::Flags::Vertex) >+ result.add(WHLSL::ShaderStage::Vertex); >+ if (flags & GPUShaderStageBit::Flags::Fragment) >+ result.add(WHLSL::ShaderStage::Fragment); >+ if (flags & GPUShaderStageBit::Flags::Compute) >+ result.add(WHLSL::ShaderStage::Compute); >+ return result; >+} >+ >+static Optional<WHLSL::Binding::BindingDetails> convertBindingType(GPUBindGroupLayout::InternalBindingDetails internalBindingDetails) >+{ >+ return WTF::visit(WTF::makeVisitor([&](GPUBindGroupLayout::UniformBuffer uniformBuffer) -> Optional<WHLSL::Binding::BindingDetails> { >+ return { WHLSL::UniformBufferBinding { uniformBuffer.internalLengthName } }; >+ }, [&](GPUBindGroupLayout::DynamicUniformBuffer) -> Optional<WHLSL::Binding::BindingDetails> { >+ return WTF::nullopt; >+ }, [&](GPUBindGroupLayout::Sampler) -> Optional<WHLSL::Binding::BindingDetails> { >+ return { WHLSL::SamplerBinding { } }; >+ }, [&](GPUBindGroupLayout::SampledTexture) -> Optional<WHLSL::Binding::BindingDetails> { >+ return { WHLSL::TextureBinding { } }; >+ }, [&](GPUBindGroupLayout::StorageBuffer storageBuffer) -> Optional<WHLSL::Binding::BindingDetails> { >+ return { WHLSL::StorageBufferBinding { storageBuffer.internalLengthName } }; >+ }, [&](GPUBindGroupLayout::DynamicStorageBuffer) -> Optional<WHLSL::Binding::BindingDetails> { >+ return WTF::nullopt; >+ }), internalBindingDetails); >+} >+ >+Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout& layout) >+{ >+ WHLSL::Layout result; >+ if (layout.bindGroupLayouts().size() > std::numeric_limits<unsigned>::max()) >+ return WTF::nullopt; >+ for (size_t i = 0; i < layout.bindGroupLayouts().size(); ++i) { >+ const auto& bindGroupLayout = layout.bindGroupLayouts()[i]; >+ WHLSL::BindGroup bindGroup; >+ bindGroup.name = static_cast<unsigned>(i); >+ for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) { >+ const auto& bindingDetails = keyValuePair.value; >+ WHLSL::Binding binding; >+ binding.visibility = convertShaderStageFlags(bindingDetails.externalBinding.visibility); >+ if (auto bindingType = convertBindingType(bindingDetails.internalBindingDetails)) >+ binding.binding = *bindingType; >+ else >+ return WTF::nullopt; >+ if (bindingDetails.externalBinding.binding > std::numeric_limits<unsigned>::max()) >+ return WTF::nullopt; >+ binding.externalName = bindingDetails.externalBinding.binding; >+ binding.internalName = bindingDetails.internalName; >+ bindGroup.bindings.append(WTFMove(binding)); >+ } >+ result.append(WTFMove(bindGroup)); >+ } >+ return result; >+} >+ >+} // namespace WebCore >+ >+#endif // ENABLE(WEBGPU) >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.h >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.h (nonexistent) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPUPipelineMetalConvertLayout.h (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#if ENABLE(WEBGPU) >+ >+#include "WHLSLPipelineDescriptor.h" >+#include <wtf/Optional.h> >+ >+namespace WebCore { >+ >+class GPUPipelineLayout; >+ >+Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout&); >+ >+} >+ >+#endif >Index: Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm (working copy) >@@ -30,6 +30,7 @@ > > #import "GPUDevice.h" > #import "GPULimits.h" >+#import "GPUPipelineMetalConvertLayout.h" > #import "GPUUtils.h" > #import "Logging.h" > #import "WHLSLPrepare.h" >@@ -98,34 +99,6 @@ static WHLSL::VertexFormat convertVertex > } > } > >-static OptionSet<WHLSL::ShaderStage> convertShaderStageFlags(GPUShaderStageFlags flags) >-{ >- OptionSet<WHLSL::ShaderStage> result; >- if (flags & GPUShaderStageBit::Flags::Vertex) >- result.add(WHLSL::ShaderStage::Vertex); >- if (flags & GPUShaderStageBit::Flags::Fragment) >- result.add(WHLSL::ShaderStage::Fragment); >- if (flags & GPUShaderStageBit::Flags::Compute) >- result.add(WHLSL::ShaderStage::Compute); >- return result; >-} >- >-static Optional<WHLSL::BindingType> convertBindingType(GPUBindingType type) >-{ >- switch (type) { >- case GPUBindingType::UniformBuffer: >- return WHLSL::BindingType::UniformBuffer; >- case GPUBindingType::Sampler: >- return WHLSL::BindingType::Sampler; >- case GPUBindingType::SampledTexture: >- return WHLSL::BindingType::Texture; >- case GPUBindingType::StorageBuffer: >- return WHLSL::BindingType::StorageBuffer; >- default: >- return WTF::nullopt; >- } >-} >- > static Optional<WHLSL::TextureFormat> convertTextureFormat(GPUTextureFormat format) > { > switch (format) { >@@ -367,33 +340,6 @@ static bool trySetColorStates(const char > return true; > } > >-static Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout& layout) >-{ >- WHLSL::Layout result; >- if (layout.bindGroupLayouts().size() > std::numeric_limits<unsigned>::max()) >- return WTF::nullopt; >- for (size_t i = 0; i < layout.bindGroupLayouts().size(); ++i) { >- const auto& bindGroupLayout = layout.bindGroupLayouts()[i]; >- WHLSL::BindGroup bindGroup; >- bindGroup.name = static_cast<unsigned>(i); >- for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) { >- const auto& gpuBindGroupLayoutBinding = keyValuePair.value; >- WHLSL::Binding binding; >- binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility); >- if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type)) >- binding.bindingType = *bindingType; >- else >- return WTF::nullopt; >- if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max()) >- return WTF::nullopt; >- binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding); >- bindGroup.bindings.append(WTFMove(binding)); >- } >- result.append(WTFMove(bindGroup)); >- } >- return result; >-} >- > static bool trySetMetalFunctions(const char* const functionName, MTLLibrary *vertexMetalLibrary, MTLLibrary *fragmentMetalLibrary, MTLRenderPipelineDescriptor *mtlDescriptor, const String& vertexEntryPointName, const String& fragmentEntryPointName) > { > #if LOG_DISABLED >@@ -464,13 +410,13 @@ static bool trySetFunctions(const char* > if (!whlslCompileResult) > return false; > >- WTFLogAlways("Metal Source: %s", whlslCompileResult->metalSource.utf8().data()); >- > NSError *error = nil; > > BEGIN_BLOCK_OBJC_EXCEPTIONS; > vertexLibrary = adoptNS([device.platformDevice() newLibraryWithSource:whlslCompileResult->metalSource options:nil error:&error]); > END_BLOCK_OBJC_EXCEPTIONS; >+ if (!vertexLibrary) >+ NSLog(@"%@", error); > > ASSERT(vertexLibrary); > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195771 Once we zero-fill variables, there should be no warnings, so we should be able to ASSERT(!error) here. >@@ -540,6 +486,11 @@ static RetainPtr<MTLRenderPipelineDescri > > static RetainPtr<MTLRenderPipelineState> tryCreateMtlRenderPipelineState(const char* const functionName, const GPURenderPipelineDescriptor& descriptor, const GPUDevice& device) > { >+ if (!device.platformDevice()) { >+ LOG(WebGPU, "GPUComputePipeline::tryCreate(): Invalid GPUDevice!"); >+ return nullptr; >+ } >+ > auto mtlDescriptor = convertRenderPipelineDescriptor(functionName, descriptor, device); > if (!mtlDescriptor) > return nullptr; >@@ -548,7 +499,7 @@ static RetainPtr<MTLRenderPipelineState> > > BEGIN_BLOCK_OBJC_EXCEPTIONS; > >- NSError *error = [NSError errorWithDomain:@"com.apple.WebKit.GPU" code:1 userInfo:nil]; >+ NSError *error = nil; > pipeline = adoptNS([device.platformDevice() newRenderPipelineStateWithDescriptor:mtlDescriptor.get() error:&error]); > if (!pipeline) > LOG(WebGPU, "%s: %s!", functionName, error.localizedDescription.UTF8String); >Index: LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html >=================================================================== >--- LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html (revision 246326) >+++ LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html (working copy) >@@ -74,10 +74,10 @@ async function start() { > const vertexBuffer1 = device.createBuffer(vertexBuffer1Descriptor); > const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync(); > const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer); >- vertexBuffer1Descriptor[0] = 1; >- vertexBuffer1Descriptor[1] = 1; >- vertexBuffer1Descriptor[2] = 1; >- vertexBuffer1Descriptor[3] = 1; >+ vertexBuffer1Float32Array[0] = 1; >+ vertexBuffer1Float32Array[1] = 1; >+ vertexBuffer1Float32Array[2] = 1; >+ vertexBuffer1Float32Array[3] = 1; > vertexBuffer1.unmap(); > > const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >Index: LayoutTests/webgpu/whlsl.html >=================================================================== >--- LayoutTests/webgpu/whlsl.html (revision 246326) >+++ LayoutTests/webgpu/whlsl.html (working copy) >@@ -69,10 +69,10 @@ async function start() { > const vertexBuffer1 = device.createBuffer(vertexBuffer1Descriptor); > const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync(); > const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer); >- vertexBuffer1Descriptor[0] = 1; >- vertexBuffer1Descriptor[1] = 1; >- vertexBuffer1Descriptor[2] = 1; >- vertexBuffer1Descriptor[3] = 1; >+ vertexBuffer1Float32Array[0] = 1; >+ vertexBuffer1Float32Array[1] = 1; >+ vertexBuffer1Float32Array[2] = 1; >+ vertexBuffer1Float32Array[3] = 1; > vertexBuffer1.unmap(); > > const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};
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 198600
:
371908
|
371912
|
372013
|
372074
|
372127
|
372128