WebKit Bugzilla
Attachment 371908 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
c-backup.diff (text/plain), 316.51 KB, created by
Saam Barati
on 2019-06-11 18:55:21 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-06-11 18:55:21 PDT
Size:
316.51 KB
patch
obsolete
>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/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) >@@ -58,7 +58,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; > >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]; >+ >+ appendIndexAssignment(propertyAccessExpression, indexVariable); > >- auto callExpression = getterCall(dotExpression, previousLeftValue, pointerToPreviousLeftValue); >+ 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,106 @@ 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()); >+ >+ 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) >+{ >+ Visitor::visit(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,6 +375,63 @@ native typedef TextureDepth2DArray<float > native typedef RWTextureDepth2DArray<float>; > native typedef TextureDepthCube<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.x(float4); > native float operator.y(float4); > native float operator.z(float4); >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"); > } >@@ -257,9 +273,28 @@ 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")); >+ } > } > } > >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; >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 { >@@ -153,12 +155,44 @@ 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) >+ { >+ if (!expression.typeAnnotation().leftAddressSpace()) >+ dataLogLn("not an lvalue!!!: ", ExpressionDumper(expression)); >+ 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 }; >@@ -246,7 +280,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 +298,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 +310,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 +339,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 +349,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 +364,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 +376,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 +409,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 +417,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 +425,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 +442,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 +450,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 +460,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 +468,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 +512,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 +520,11 @@ 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")); >+ appendRightValue(assignmentExpression, rightName); > } > > void FunctionDefinitionWriter::visit(AST::CallExpression& callExpression) >@@ -496,7 +532,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 +545,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 +553,31 @@ 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")); >+ // OOPS: nullptr check here! >+ m_stringBuilder.append(makeString("if (", pointerName, ") ", variableName, " = *", right, ";\n")); >+ m_stringBuilder.append(makeString("else for (size_t i = 0; i < sizeof(", m_typeNamer.mangledNameForType(dereferenceExpression.resolvedType()), "); ++i) static_cast<thread char*>(static_cast<thread void*>(&", variableName, "))[i] = 0;\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 +590,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 +615,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 +636,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") >@@ -246,9 +231,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 +361,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 +379,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/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/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/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/GPURenderPipelineMetal.mm >=================================================================== >--- Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm (revision 246326) >+++ Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm (working copy) >@@ -110,20 +110,21 @@ static OptionSet<WHLSL::ShaderStage> con > return result; > } > >-static Optional<WHLSL::BindingType> convertBindingType(GPUBindingType type) >+static Optional<WHLSL::Binding::BindingDetails> convertBindingType(GPUBindGroupLayout::InternalBindingDetails internalBindingDetails) > { >- 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::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); > } > > static Optional<WHLSL::TextureFormat> convertTextureFormat(GPUTextureFormat format) >@@ -377,16 +378,17 @@ static Optional<WHLSL::Layout> convertLa > WHLSL::BindGroup bindGroup; > bindGroup.name = static_cast<unsigned>(i); > for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) { >- const auto& gpuBindGroupLayoutBinding = keyValuePair.value; >+ const auto& bindingDetails = keyValuePair.value; > WHLSL::Binding binding; >- binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility); >- if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type)) >- binding.bindingType = *bindingType; >+ binding.visibility = convertShaderStageFlags(bindingDetails.externalBinding.visibility); >+ if (auto bindingType = convertBindingType(bindingDetails.internalBindingDetails)) >+ binding.binding = *bindingType; > else > return WTF::nullopt; >- if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max()) >+ if (bindingDetails.externalBinding.binding > std::numeric_limits<unsigned>::max()) > return WTF::nullopt; >- binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding); >+ binding.externalName = bindingDetails.externalBinding.binding; >+ binding.internalName = bindingDetails.internalName; > bindGroup.bindings.append(WTFMove(binding)); > } > result.append(WTFMove(bindGroup)); >@@ -471,6 +473,8 @@ static bool trySetFunctions(const char* > 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. >Index: LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+thread Bar* operator&.q(thread Baz* b) { >+ return &b->p; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b.q.w.y = 1.0; >+ return float4(b.q.w.y, b.q.w.y, b.q.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue.html (working copy) >@@ -0,0 +1,110 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander.html (working copy) >@@ -0,0 +1,106 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+Foo generateFoo() { >+ Foo f; >+ f.x = 1.0; >+ return f; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ return float4(generateFoo().y, generateFoo().y, generateFoo().y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/getter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/getter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/getter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/getter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/getter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/getter.html (working copy) >@@ -0,0 +1,102 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Foo f; >+ f.x = 1.0; >+ return float4(f.y, f.y, f.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+thread Bar* operator&[](thread Baz* b, uint index) { >+ return &b->p; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b[1][2][3] = 1.0; >+ return float4(b[1][2][3], b[1][2][3], b[1][2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html (working copy) >@@ -0,0 +1,110 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[1][2] = 1.0; >+ return float4(b[1][2], b[1][2], b[1][2], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander.html (working copy) >@@ -0,0 +1,106 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+Foo generateFoo() { >+ Foo f; >+ f.x = 1.0; >+ return f; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ return float4(generateFoo()[0], generateFoo()[1], generateFoo()[2], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-getter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-getter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-getter.html (working copy) >@@ -0,0 +1,101 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return float(index); >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Foo f; >+ return float4(f[1], f[1], f[1], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html (working copy) >@@ -0,0 +1,133 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+Bar operator[](Baz b, uint index) { >+ return b.p; >+} >+ >+Baz operator[]=(Baz b, uint index, Bar a) { >+ b.p = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b[2][3][4] = 1.0; >+ return float4(b[2][3][4], b[2][3][4], b[2][3][4], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html (working copy) >@@ -0,0 +1,120 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ Foo foo; >+ foo.x = 1.0; >+ b[1] = foo; >+ foo = b[1]; >+ return float4(foo.x, foo.x, foo.x, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html (working copy) >@@ -0,0 +1,133 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+Bar operator.q(Baz b) { >+ return b.p; >+} >+ >+Baz operator.q=(Baz b, Bar a) { >+ b.p = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b.q.w.y = 1.0; >+ return float4(b.q.w.y, b.q.w.y, b.q.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html (working copy) >@@ -0,0 +1,120 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >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}; >Index: LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-abstract-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-3-levels.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+thread Bar* operator&.q(thread Baz* b) { >+ return &b->p; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b.q.w.y = 1.0; >+ return float4(b.q.w.y, b.q.w.y, b.q.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander-lvalue.html (working copy) >@@ -0,0 +1,110 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/ander.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/ander.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/ander.html (working copy) >@@ -0,0 +1,106 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&.y(thread Foo* f) { >+ return &f->x; >+} >+ >+Foo generateFoo() { >+ Foo f; >+ f.x = 1.0; >+ return f; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ return float4(generateFoo().y, generateFoo().y, generateFoo().y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/getter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/getter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/getter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/getter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/getter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/getter.html (working copy) >@@ -0,0 +1,102 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Foo f; >+ f.x = 1.0; >+ return float4(f.y, f.y, f.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-abstract-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-3-levels.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+thread Bar* operator&[](thread Baz* b, uint index) { >+ return &b->p; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b[1][2][3] = 1.0; >+ return float4(b[1][2][3], b[1][2][3], b[1][2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander-lvalue.html (working copy) >@@ -0,0 +1,110 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[1][2] = 1.0; >+ return float4(b[1][2], b[1][2], b[1][2], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-ander.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-ander.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-ander.html (working copy) >@@ -0,0 +1,106 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+Foo generateFoo() { >+ Foo f; >+ f.x = 1.0; >+ return f; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ return float4(generateFoo()[0], generateFoo()[1], generateFoo()[2], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-getter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-getter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-getter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-getter.html (working copy) >@@ -0,0 +1,101 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return float(index); >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Foo f; >+ return float4(f[1], f[1], f[1], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-3-levels.html (working copy) >@@ -0,0 +1,133 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+Bar operator[](Baz b, uint index) { >+ return b.p; >+} >+ >+Baz operator[]=(Baz b, uint index, Bar a) { >+ b.p = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b[2][3][4] = 1.0; >+ return float4(b[2][3][4], b[2][3][4], b[2][3][4], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-abstract-lvalue.html (working copy) >@@ -0,0 +1,120 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator[](Foo f, uint index) { >+ return f.x; >+} >+ >+Foo operator[]=(Foo f, uint index, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&[](thread Bar* b, uint index) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b[2][3] = 1.0; >+ return float4(b[2][3], b[2][3], b[2][3], 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/indexer-setter.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/indexer-setter.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/indexer-setter.html (working copy) >@@ -0,0 +1,118 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+thread float* operator&[](thread Foo* f, uint index) { >+ return &f->x; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator[](Bar b, uint index) { >+ return b.z; >+} >+ >+Bar operator[]=(Bar b, uint index, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ Foo foo; >+ foo.x = 1.0; >+ b[1] = foo; >+ foo = b[1]; >+ return float4(foo.x, foo.x, foo.x, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-3-levels.html (working copy) >@@ -0,0 +1,133 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+struct Baz { >+ Bar p; >+} >+ >+Bar operator.q(Baz b) { >+ return b.p; >+} >+ >+Baz operator.q=(Baz b, Bar a) { >+ b.p = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Baz b; >+ b.q.w.y = 1.0; >+ return float4(b.q.w.y, b.q.w.y, b.q.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-abstract-lvalue.html (working copy) >@@ -0,0 +1,120 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+Foo operator.w(Bar b) { >+ return b.z; >+} >+ >+Bar operator.w=(Bar b, Foo a) { >+ b.z = a; >+ return b; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-lvalue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/propertyresolver/setter-lvalue.html >=================================================================== >--- LayoutTests/webgpu/propertyresolver/setter-lvalue.html (nonexistent) >+++ LayoutTests/webgpu/propertyresolver/setter-lvalue.html (working copy) >@@ -0,0 +1,115 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position { >+ return position; >+} >+ >+struct Foo { >+ float x; >+} >+ >+float operator.y(Foo f) { >+ return f.x; >+} >+ >+Foo operator.y=(Foo f, float x) { >+ f.x = x; >+ return f; >+} >+ >+struct Bar { >+ Foo z; >+} >+ >+thread Foo* operator&.w(thread Bar* b) { >+ return &b->z; >+} >+ >+fragment float4 fragmentShader() : SV_Target 0 { >+ Bar b; >+ b.w.y = 1.0; >+ return float4(b.w.y, b.w.y, b.w.y, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const pipelineLayoutDescriptor = {bindGroupLayouts: []}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer = device.createBuffer(vertexBufferDescriptor); >+ const vertexBufferArrayBuffer = await vertexBuffer.mapWriteAsync(); >+ const vertexBufferFloat32Array = new Float32Array(vertexBufferArrayBuffer); >+ vertexBufferFloat32Array[0] = -0.5; >+ vertexBufferFloat32Array[1] = -0.5; >+ vertexBufferFloat32Array[2] = 1.0; >+ vertexBufferFloat32Array[3] = 1; >+ vertexBufferFloat32Array[4] = -0.5; >+ vertexBufferFloat32Array[5] = 0.5; >+ vertexBufferFloat32Array[6] = 1.0; >+ vertexBufferFloat32Array[7] = 1; >+ vertexBufferFloat32Array[8] = 0.5; >+ vertexBufferFloat32Array[9] = -0.5; >+ vertexBufferFloat32Array[10] = 1.0; >+ vertexBufferFloat32Array[11] = 1; >+ vertexBufferFloat32Array[12] = 0.5; >+ vertexBufferFloat32Array[13] = 0.5; >+ vertexBufferFloat32Array[14] = 1.0; >+ vertexBufferFloat32Array[15] = 1; >+ vertexBuffer.unmap(); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198600
:
371908
|
371912
|
372013
|
372074
|
372127
|
372128