WebKit Bugzilla
Attachment 371042 Details for
Bug 198399
: [WHLSL] Educate the property resolver about IndexExpressions
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP
bug-198399-20190531000048.patch (text/plain), 157.68 KB, created by
Myles C. Maxfield
on 2019-05-31 00:00:49 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Myles C. Maxfield
Created:
2019-05-31 00:00:49 PDT
Size:
157.68 KB
patch
obsolete
>Subversion Revision: 245944 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 10e75b0e622764cd414e0d3f7cef2dd5cb13a4df..ae4c2e1b0e4665340f7e2574bbc6c3bbffeacebe 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,28 @@ >+2019-05-30 Myles C. Maxfield <mmaxfield@apple.com> >+ >+ [WHLSL] Educate the property resolver about IndexExpressions >+ https://bugs.webkit.org/show_bug.cgi?id=198399 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No new tests (OOPS!). >+ >+ * Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h: >+ (WebCore::WHLSL::AST::IndexExpression::takeIndex): >+ * Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h: >+ * Modules/webgpu/WHLSL/WHLSLChecker.cpp: >+ (WebCore::WHLSL::Checker::finishVisiting): >+ (WebCore::WHLSL::Checker::visit): >+ * Modules/webgpu/WHLSL/WHLSLInferTypes.h: >+ * Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp: >+ (WebCore::WHLSL::PropertyResolver::visit): >+ (WebCore::WHLSL::setterCall): >+ (WebCore::WHLSL::getterCall): >+ (WebCore::WHLSL::modify): >+ (WebCore::WHLSL::PropertyResolver::simplifyRightValue): >+ (WebCore::WHLSL::LeftValueSimplifier::finishVisiting): >+ (WebCore::WHLSL::LeftValueSimplifier::visit): >+ > 2019-05-30 Ryan Haddad <ryanhaddad@apple.com> > > Unreviewed, rolling out r245890, 245887. >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >index 425d134667851dab85c827b250cb57afdefc2dde..aba33d5d07834176360a8b3bf8173dbae300281f 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAddressSpace.h >@@ -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: >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h >index 65f6873b46909dead4cb20262b7536e117e57d22..b45424fd3fd387ed0a3ffb1d103a765560088dbc 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLEntryPointType.h >@@ -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: >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h >index aa197b5af43bd60388c7185ad146e8ec03d32e8c..7adf1e8e2289c1d68b302e2bb983cee574d8b8d2 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLIndexExpression.h >@@ -68,6 +68,7 @@ public: > } > > Expression& indexExpression() { return m_index; } >+ UniqueRef<Expression> takeIndex() { return WTFMove(m_index); } > > private: > UniqueRef<Expression> m_index; >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h >index 8811ac9ad427dd02e7f141b06432bc5033869653..1e6ce164c6cbdb1938c92b594e0060e091295944 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h >@@ -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; } >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >index 543f8c0be7009bc990a35be677198c617bfcd0ac..b9695aedb544eb9e9af2aa398c3b954e0c0e4faa 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >@@ -29,6 +29,7 @@ > #if ENABLE(WEBGPU) > > #include "NotImplemented.h" >+#include "WHLSLAddressSpace.h" > #include "WHLSLArrayReferenceType.h" > #include "WHLSLArrayType.h" > #include "WHLSLAssignmentExpression.h" >@@ -480,15 +481,6 @@ void FunctionDefinitionWriter::visit(AST::VariableDeclaration& variableDeclarati > > void FunctionDefinitionWriter::visit(AST::AssignmentExpression& assignmentExpression) > { >- if (is<AST::DereferenceExpression>(assignmentExpression.left())) { >- checkErrorAndVisit(downcast<AST::DereferenceExpression>(assignmentExpression.left()).pointer()); >- auto leftName = m_stack.takeLast(); >- checkErrorAndVisit(assignmentExpression.right()); >- auto rightName = m_stack.takeLast(); >- m_stringBuilder.append(makeString('*', leftName, " = ", rightName, ";\n")); >- m_stack.append(rightName); >- return; >- } > checkErrorAndVisit(assignmentExpression.left()); > auto leftName = m_stack.takeLast(); > checkErrorAndVisit(assignmentExpression.right()); >@@ -533,7 +525,7 @@ void FunctionDefinitionWriter::visit(AST::DereferenceExpression& dereferenceExpr > checkErrorAndVisit(dereferenceExpression.pointer()); > auto right = m_stack.takeLast(); > auto variableName = generateNextVariableName(); >- m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(dereferenceExpression.resolvedType()), ' ', variableName, " = *", right, ";\n")); >+ m_stringBuilder.append(makeString(AST::toString(*dereferenceExpression.typeAnnotation().leftAddressSpace()), ' ', m_typeNamer.mangledNameForType(dereferenceExpression.resolvedType()), "& ", variableName, " = *", right, ";\n")); > m_stack.append(variableName); > } > >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >index 38e7a71876ee850b0d758945ad1971fec91fd6e0..69dffdfe5a5c413e118753c38d1d39c014c8082f 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp >@@ -63,21 +63,6 @@ static String mapFunctionName(String& functionName) > 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") >@@ -375,7 +360,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > 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"); >@@ -393,7 +378,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara > 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(); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >index 75578a49b29a894ddf70211d6e5e1ce9775ae7ac..73fce5f6fe40ea0e2d94a2651fc9f5dff7cbe63c 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >@@ -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" >@@ -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; >@@ -555,6 +558,8 @@ bool Checker::checkShaderType(const AST::FunctionDefinition& functionDefinition) > > void Checker::visit(AST::FunctionDefinition& functionDefinition) > { >+ if (functionDefinition.entryPointType()) >+ WTFLogAlways("Function type %s", toString(*functionDefinition.entryPointType()).utf8().data()); > if (functionDefinition.entryPointType()) { > if (!checkShaderType(functionDefinition)) { > setError(); >@@ -576,6 +581,8 @@ void Checker::visit(AST::FunctionDefinition& functionDefinition) > } > > Visitor::visit(functionDefinition); >+ if (functionDefinition.entryPointType()) >+ WTFLogAlways("End Function type %s", toString(*functionDefinition.entryPointType()).utf8().data()); > } > > static Optional<UniqueRef<AST::UnnamedType>> matchAndCommit(ResolvingType& left, ResolvingType& right) >@@ -966,41 +973,49 @@ void Checker::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpress > assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *leftAddressSpace, leftValueType->clone())); > } > >-void Checker::visit(AST::DotExpression& dotExpression) >+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); > if (!baseUnnamedType) > return; > >+ WTFLogAlways("asdf %s", propertyAccessExpression.getterFunctionName().utf8().data()); >+ for (AST::FunctionDeclaration& overload : propertyAccessExpression.possibleGetterOverloads()) { >+ WTFLogAlways("option %s", overload.name().utf8().data()); >+ } > AST::FunctionDeclaration* getterFunction = nullptr; > AST::UnnamedType* getterReturnType = nullptr; > { > Vector<std::reference_wrapper<ResolvingType>> getterArgumentTypes { baseInfo->resolvingType }; >- getterFunction = resolveFunctionOverloadImpl(dotExpression.possibleGetterOverloads(), getterArgumentTypes, nullptr); >- if (getterFunction) >+ if (additionalArgumentType) >+ getterArgumentTypes.append(*additionalArgumentType); >+ if ((getterFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleGetterOverloads(), getterArgumentTypes, nullptr))) > 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 = resolveFunctionOverloadImpl(dotExpression.possibleAnderOverloads(), anderArgumentTypes, nullptr); >- if (anderFunction) >+ auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace(); >+ if (leftAddressSpace) { >+ ResolvingType argumentType = { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), *leftAddressSpace, baseUnnamedType->get().clone()) }; >+ Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { argumentType }; >+ if (additionalArgumentType) >+ anderArgumentTypes.append(*additionalArgumentType); >+ if ((anderFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes, nullptr))) > 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 = resolveFunctionOverloadImpl(dotExpression.possibleAnderOverloads(), threadAnderArgumentTypes, nullptr); >- if (threadAnderFunction) >+ 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 = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes, nullptr))) > 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 > } > >@@ -1023,8 +1038,11 @@ void Checker::visit(AST::DotExpression& dotExpression) > AST::UnnamedType* setterReturnType = nullptr; > { > ResolvingType fieldResolvingType(fieldType->clone()); >- Vector<std::reference_wrapper<ResolvingType>> setterArgumentTypes { baseInfo->resolvingType, fieldResolvingType }; >- setterFunction = resolveFunctionOverloadImpl(dotExpression.possibleSetterOverloads(), setterArgumentTypes, nullptr); >+ Vector<std::reference_wrapper<ResolvingType>> setterArgumentTypes { baseInfo->resolvingType }; >+ if (additionalArgumentType) >+ setterArgumentTypes.append(*additionalArgumentType); >+ setterArgumentTypes.append(fieldResolvingType); >+ setterFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleSetterOverloads(), setterArgumentTypes, nullptr); > if (setterFunction) > setterReturnType = &setterFunction->type(); > } >@@ -1034,10 +1052,10 @@ void Checker::visit(AST::DotExpression& dotExpression) > 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()) { >@@ -1047,12 +1065,20 @@ void Checker::visit(AST::DotExpression& dotExpression) > typeAnnotation = AST::AbstractLeftValue(); > } else if (!baseInfo->typeAnnotation.isRightValue() && (setterFunction || anderFunction)) > 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 +1388,7 @@ void Checker::visit(AST::CommaExpression& 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) >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h >index 173d3014497d2a3742e80670f80bc96ff0f79c4d..19fb1ffcf814414cd6a227dea8943055028eb0ac 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLInferTypes.h >@@ -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&); >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >index fa069cabce204d379ef6568e7d926073792f85e7..4843e1d93b407e416b48aefda6f08cd9e9a88c9f 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp >@@ -51,10 +51,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&); >+ bool simplifyRightValue(AST::PropertyAccessExpression&, Optional<UniqueRef<AST::Expression>>&& additionalArgument); > bool simplifyAbstractLeftValue(AST::AssignmentExpression&, AST::DotExpression&, UniqueRef<AST::Expression>&& right); > void simplifyLeftValue(AST::Expression&); > >@@ -64,7 +65,15 @@ private: > void PropertyResolver::visit(AST::DotExpression& dotExpression) > { > // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value. >- if (!simplifyRightValue(dotExpression)) >+ if (!simplifyRightValue(dotExpression, WTF::nullopt)) >+ setError(); >+} >+ >+void PropertyResolver::visit(AST::IndexExpression& indexExpression) >+{ >+ checkErrorAndVisit(indexExpression.indexExpression()); >+ // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value. >+ if (!simplifyRightValue(indexExpression, indexExpression.takeIndex())) > setError(); > } > >@@ -75,79 +84,111 @@ void PropertyResolver::visit(AST::FunctionDefinition& functionDefinition) > 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) >+static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpression& propertyAccessExpression, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory, AST::VariableDeclaration* indexVariable) > { >- if (dotExpression.anderFunction()) { >+ if (propertyAccessExpression.anderFunction()) { > // *operator&.foo(&v) = newValue >- if (!dotExpression.threadAnderFunction()) >+ if (!propertyAccessExpression.threadAnderFunction()) > return WTF::nullopt; > > 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()); >+ if (indexVariable) { >+ 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)); >+ } >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(propertyAccessExpression.threadAnderFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(propertyAccessExpression.threadAnderFunction()->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.threadAnderFunction()); >+ callExpression->setFunction(*propertyAccessExpression.threadAnderFunction()); > >- 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>(propertyAccessExpression.threadAnderFunction()->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>(propertyAccessExpression.threadAnderFunction()->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()); >+ if (indexVariable) { >+ 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)); >+ } > 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, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory, AST::VariableDeclaration* indexVariable) > { >- if (dotExpression.anderFunction()) { >+ if (propertyAccessExpression.anderFunction()) { > // *operator&.foo(&v) >- if (!dotExpression.threadAnderFunction()) >+ if (!propertyAccessExpression.threadAnderFunction()) > return WTF::nullopt; > > 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()); >+ if (indexVariable) { >+ 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)); >+ } >+ >+ auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(propertyAccessExpression.origin()), String(propertyAccessExpression.threadAnderFunction()->name()), WTFMove(arguments)); >+ callExpression->setType(propertyAccessExpression.threadAnderFunction()->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >- callExpression->setFunction(*dotExpression.threadAnderFunction()); >+ callExpression->setFunction(*propertyAccessExpression.threadAnderFunction()); > >- 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>(propertyAccessExpression.threadAnderFunction()->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()); >+ if (indexVariable) { >+ 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)); >+ } >+ >+ 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 +202,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: >@@ -188,15 +229,15 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > > > // 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 +249,29 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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). >+ 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); >+ intermediateVariables.uncheckedAppend(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(propertyAccessExpression.origin()), AST::Qualifiers(), indexExpression.indexExpression().resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt)); > } > > Vector<UniqueRef<AST::Expression>> expressions; >@@ -248,7 +310,7 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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() }); >@@ -261,9 +323,9 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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 makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(dotExpression.origin()), WTFMove(variableReference)); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference)); > ASSERT(previous->type()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone())); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone())); > makePointerExpression->setTypeAnnotation(AST::RightValue()); > return makePointerExpression; > } >@@ -274,11 +336,31 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right? > return variableReference; > }; >+ auto appendIndexAssignment = [&](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 assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference), indexExpression.takeIndex()); >+ assignmentExpression->setType(indexVariable->get().type()->clone()); >+ assignmentExpression->setTypeAnnotation(AST::RightValue()); >+ >+ expressions.append(WTFMove(assignmentExpression)); >+ }; > for (size_t i = chain.size(); --i; ) { >- AST::DotExpression& dotExpression = chain[i]; >+ AST::PropertyAccessExpression& propertyAccessExpression = chain[i]; > AST::VariableDeclaration& variableDeclaration = intermediateVariables[i - 1]; >+ Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable = indexVariables[i]; > >- auto callExpression = getterCall(dotExpression, previousLeftValue, pointerToPreviousLeftValue); >+ appendIndexAssignment(indexVariable); >+ >+ auto callExpression = getterCall(propertyAccessExpression, previousLeftValue, pointerToPreviousLeftValue, indexVariable ? &*indexVariable : nullptr); > > if (!callExpression) > return WTF::nullopt; >@@ -288,7 +370,7 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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()); > >@@ -296,7 +378,8 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > > previous = &variableDeclaration; > } >- auto lastGetterCallExpression = getterCall(chain[0], previousLeftValue, pointerToPreviousLeftValue); >+ appendIndexAssignment(indexVariables[0]); >+ auto lastGetterCallExpression = getterCall(chain[0], previousLeftValue, pointerToPreviousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr); > > // Step 3: > auto modificationResult = modification(WTFMove(lastGetterCallExpression)); >@@ -309,10 +392,11 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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, WTFMove(rightValue), [&]() -> UniqueRef<AST::Expression> { > auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration)); > ASSERT(variableDeclaration.type()); > variableReference->setType(variableDeclaration.type()->clone()); >@@ -324,12 +408,12 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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)); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference)); > ASSERT(variableDeclaration.type()); >- makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(dotExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone())); >+ makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone())); > makePointerExpression->setTypeAnnotation(AST::RightValue()); > return makePointerExpression; >- }); >+ }, indexVariable ? &*indexVariable : nullptr); > > if (!assignmentExpression) > return WTF::nullopt; >@@ -350,7 +434,7 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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() }); >@@ -361,7 +445,7 @@ static Optional<ModifyResult> modify(AST::DotExpression& dotExpression, std::fun > 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; >@@ -385,8 +469,8 @@ void PropertyResolver::visit(AST::AssignmentExpression& assignmentExpression) > 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. >+ if (!is<AST::PropertyAccessExpression>(assignmentExpression.left())) { >+ setError(); > return; > } > >@@ -394,7 +478,7 @@ void PropertyResolver::visit(AST::AssignmentExpression& assignmentExpression) > > 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 +508,8 @@ void PropertyResolver::visit(AST::ReadModifyWriteExpression& readModifyWriteExpr > // 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 +606,11 @@ void PropertyResolver::visit(AST::ReadModifyWriteExpression& readModifyWriteExpr > } > > 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; >@@ -581,27 +667,29 @@ void PropertyResolver::visit(AST::ReadModifyWriteExpression& readModifyWriteExpr > m_variableDeclarations.append(WTFMove(newVariableDeclaration)); > } > >-bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) >+bool PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression, Optional<UniqueRef<AST::Expression>>&& additionalArgument) > { >- Lexer::Token origin = dotExpression.origin(); >+ Lexer::Token origin = propertyAccessExpression.origin(); > >- checkErrorAndVisit(dotExpression.base()); >+ checkErrorAndVisit(propertyAccessExpression.base()); > >- if (auto* anderFunction = dotExpression.anderFunction()) { >- auto& base = dotExpression.base(); >+ if (auto* anderFunction = propertyAccessExpression.anderFunction()) { >+ auto& base = propertyAccessExpression.base(); > if (auto leftAddressSpace = base.typeAnnotation().leftAddressSpace()) { >- auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), dotExpression.takeBase()); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.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)); >+ if (additionalArgument) >+ arguments.append(WTFMove(*additionalArgument)); > 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() }); > return true; >@@ -609,7 +697,7 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > > // 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()) >+ if (!propertyAccessExpression.threadAnderFunction()) > return false; > > auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), base.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt); >@@ -618,7 +706,7 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > variableReference1->setType(base.resolvedType().clone()); > variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); > >- auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), dotExpression.takeBase()); >+ auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), propertyAccessExpression.takeBase()); > assignmentExpression->setType(base.resolvedType().clone()); > assignmentExpression->setTypeAnnotation(AST::RightValue()); > >@@ -632,6 +720,8 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > > Vector<UniqueRef<AST::Expression>> arguments; > arguments.append(WTFMove(makePointerExpression)); >+ if (additionalArgument) >+ arguments.append(WTFMove(*additionalArgument)); > auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments)); > callExpression->setType(anderFunction->type().clone()); > callExpression->setTypeAnnotation(AST::RightValue()); >@@ -644,7 +734,7 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > Vector<UniqueRef<AST::Expression>> expressions; > expressions.append(WTFMove(assignmentExpression)); > expressions.append(WTFMove(dereferenceExpression)); >- auto* commaExpression = AST::replaceWith<AST::CommaExpression>(dotExpression, WTFMove(origin), WTFMove(expressions)); >+ auto* commaExpression = AST::replaceWith<AST::CommaExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(expressions)); > commaExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone()); > commaExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); > >@@ -652,11 +742,13 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > return true; > } > >- 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 (additionalArgument) >+ arguments.append(WTFMove(*additionalArgument)); >+ 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()); >@@ -664,45 +756,59 @@ bool PropertyResolver::simplifyRightValue(AST::DotExpression& dotExpression) > } > > 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&, Optional<UniqueRef<AST::Expression>>&& additionalArgument); > }; > >-void LeftValueSimplifier::visit(AST::DotExpression& dotExpression) >+void LeftValueSimplifier::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpression, Optional<UniqueRef<AST::Expression>>&& additionalArgument) > { >- Visitor::visit(dotExpression); >- ASSERT(dotExpression.base().typeAnnotation().leftAddressSpace()); >- ASSERT(dotExpression.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()); >+ ASSERT(propertyAccessExpression.base().typeAnnotation().leftAddressSpace()); >+ ASSERT(propertyAccessExpression.anderFunction()); >+ >+ Lexer::Token origin = propertyAccessExpression.origin(); >+ auto* anderFunction = propertyAccessExpression.anderFunction(); >+ auto& base = propertyAccessExpression.base(); >+ auto leftAddressSpace = *propertyAccessExpression.base().typeAnnotation().leftAddressSpace(); >+ auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.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)); >+ if (additionalArgument) >+ arguments.append(WTFMove(*additionalArgument)); > 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, WTF::nullopt); >+} >+ >+void LeftValueSimplifier::visit(AST::IndexExpression& indexExpression) >+{ >+ Visitor::visit(indexExpression); >+ PropertyResolver().Visitor::visit(indexExpression.indexExpression()); >+ finishVisiting(indexExpression, indexExpression.takeIndex()); >+} >+ > 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); > } > >diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >index 945d0ceefaa39ce5074607d2c4493cf397e983de..f89787d17804c7b4f80dc919c70da3f7a75e2b98 100644 >--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeStructureAccessors.cpp >@@ -44,7 +44,7 @@ bool synthesizeStructureAccessors(Program& program) > 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; >@@ -64,7 +64,7 @@ bool synthesizeStructureAccessors(Program& program) > 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 { >diff --git a/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations-expected.html b/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations.html b/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations.html >deleted file mode 100644 >index b35e6c2cc251f4a3f61c86bc8a0a329cae200d7f..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations.html >+++ /dev/null >@@ -1,123 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >-struct VertexOut { >- float4 position : SV_Position; >- float shade : attribute(0); >-} >- >-vertex VertexOut vertexShader(float4 position : attribute(173), float shade : attribute(498)) { >- VertexOut result; >- result.position = position; >- result.shade = shade; >- return result; >-} >- >-fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >- return float4(shade, shade, shade, 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: 173, format: "float4"}; >- const attribute1 = {shaderLocation: 498, format: "float", offset: 16}; >- const input0 = {stride: 20, attributeSet: [attribute0, attribute1]}; >- const inputs = [input0]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1.0; >- vertexBuffer0Float32Array[4] = 1.0; >- >- vertexBuffer0Float32Array[5] = -0.5; >- vertexBuffer0Float32Array[6] = 0.5; >- vertexBuffer0Float32Array[7] = 1.0; >- vertexBuffer0Float32Array[8] = 1.0; >- vertexBuffer0Float32Array[9] = 1.0; >- >- vertexBuffer0Float32Array[10] = 0.5; >- vertexBuffer0Float32Array[11] = -0.5; >- vertexBuffer0Float32Array[12] = 1.0; >- vertexBuffer0Float32Array[13] = 1.0; >- vertexBuffer0Float32Array[14] = 1.0; >- >- vertexBuffer0Float32Array[15] = 0.5; >- vertexBuffer0Float32Array[16] = 0.5; >- vertexBuffer0Float32Array[17] = 1.0; >- vertexBuffer0Float32Array[18] = 1.0; >- vertexBuffer0Float32Array[19] = 1.0; >- vertexBuffer0.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check-expected.html b/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check.html b/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check.html >deleted file mode 100644 >index 9507d6b2b6c2b769b0ed763916c0268ed713080e..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check.html >+++ /dev/null >@@ -1,129 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >-struct VertexOut { >- float4 position : SV_Position; >- float shade : attribute(0); >-} >- >-vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >- VertexOut result; >- >- thread float* ptr2 = &shade; >- *ptr2 = shade; >- >- result.position = position; >- result.shade = *ptr2; >- >- return result; >-} >- >-fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >- return float4(shade, shade, shade, 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", offset: 0}; >- const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >- const attributes = [attribute0, attribute1]; >- const input0 = {stride: 20, attributeSet: attributes}; >- const inputs = [input0]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1.0; >- vertexBuffer0Float32Array[4] = 1.0; >- >- vertexBuffer0Float32Array[5] = -0.5; >- vertexBuffer0Float32Array[6] = 0.5; >- vertexBuffer0Float32Array[7] = 1.0; >- vertexBuffer0Float32Array[8] = 1.0; >- vertexBuffer0Float32Array[9] = 1.0; >- >- vertexBuffer0Float32Array[10] = 0.5; >- vertexBuffer0Float32Array[11] = -0.5; >- vertexBuffer0Float32Array[12] = 1.0; >- vertexBuffer0Float32Array[13] = 1.0; >- vertexBuffer0Float32Array[14] = 1.0; >- >- vertexBuffer0Float32Array[15] = 0.5; >- vertexBuffer0Float32Array[16] = 0.5; >- vertexBuffer0Float32Array[17] = 1.0; >- vertexBuffer0Float32Array[18] = 1.0; >- vertexBuffer0Float32Array[19] = 1.0; >- vertexBuffer0.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum-expected.html b/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html b/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html >deleted file mode 100644 >index 2f8edd3bd146d3aecc6603e6907f7cf4d948ac6a..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html >+++ /dev/null >@@ -1,124 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >- >-enum DontCrash { >- Value >-} >- >-vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position { >- return position; >-} >- >-fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 { >- return position; >-} >-`; >-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 attribute1 = {shaderLocation: 1, format: "float"}; >- const input0 = {stride: 16, attributeSet: [attribute0]}; >- const input1 = {stride: 4, attributeSet: [attribute1]}; >- const inputs = [input0, input1]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1; >- vertexBuffer0Float32Array[4] = -0.5; >- vertexBuffer0Float32Array[5] = 0.5; >- vertexBuffer0Float32Array[6] = 1.0; >- vertexBuffer0Float32Array[7] = 1; >- vertexBuffer0Float32Array[8] = 0.5; >- vertexBuffer0Float32Array[9] = -0.5; >- vertexBuffer0Float32Array[10] = 1.0; >- vertexBuffer0Float32Array[11] = 1; >- vertexBuffer0Float32Array[12] = 0.5; >- vertexBuffer0Float32Array[13] = 0.5; >- vertexBuffer0Float32Array[14] = 1.0; >- vertexBuffer0Float32Array[15] = 1; >- vertexBuffer0.unmap(); >- >- const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- 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; >- vertexBuffer1.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 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> >diff --git a/LayoutTests/webgpu/whlsl-dot-expressions-expected.html b/LayoutTests/webgpu/whlsl-dot-expressions-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dot-expressions-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-dot-expressions.html b/LayoutTests/webgpu/whlsl-dot-expressions.html >deleted file mode 100644 >index 00563226f11bdfcebeebff8b802fbff18ef9e687..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-dot-expressions.html >+++ /dev/null >@@ -1,124 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >-struct VertexOut { >- float4 position : SV_Position; >- float shade : attribute(0); >-} >- >-vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >- VertexOut result; >- result.position = position; >- result.shade = shade; >- return result; >-} >- >-fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >- return float4(shade, shade, shade, 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 attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >- const attributes = [attribute0, attribute1]; >- const input0 = {stride: 20, attributeSet: attributes}; >- const inputs = [input0]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1.0; >- vertexBuffer0Float32Array[4] = 1.0; >- >- vertexBuffer0Float32Array[5] = -0.5; >- vertexBuffer0Float32Array[6] = 0.5; >- vertexBuffer0Float32Array[7] = 1.0; >- vertexBuffer0Float32Array[8] = 1.0; >- vertexBuffer0Float32Array[9] = 1.0; >- >- vertexBuffer0Float32Array[10] = 0.5; >- vertexBuffer0Float32Array[11] = -0.5; >- vertexBuffer0Float32Array[12] = 1.0; >- vertexBuffer0Float32Array[13] = 1.0; >- vertexBuffer0Float32Array[14] = 1.0; >- >- vertexBuffer0Float32Array[15] = 0.5; >- vertexBuffer0Float32Array[16] = 0.5; >- vertexBuffer0Float32Array[17] = 1.0; >- vertexBuffer0Float32Array[18] = 1.0; >- vertexBuffer0Float32Array[19] = 1.0; >- vertexBuffer0.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl-expected.html b/LayoutTests/webgpu/whlsl-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue-expected.html b/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue-expected.html >deleted file mode 100644 >index f417050f9a743f05e9006fc91ac64d502dadd633..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue-expected.html >+++ /dev/null >@@ -1,19 +0,0 @@ >-<!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> >diff --git a/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue.html b/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue.html >deleted file mode 100644 >index f72ad54927e36359684282e8fbe26471de4d4eb8..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue.html >+++ /dev/null >@@ -1,138 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >- >-struct Bar { >- float shade; >-} >-struct Foo { >- Bar bar; >-} >- >-struct Wrapper { >- Foo foo; >-} >- >-struct VertexOut { >- float4 position : SV_Position; >- float shade : attribute(0); >-} >- >-vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >- Wrapper wrapper; >- wrapper.foo.bar.shade = shade; >- VertexOut result; >- result.position = position; >- result.shade = wrapper.foo.bar.shade; >- return result; >-} >- >-fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >- return float4(shade, shade, shade, 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 attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >- const attributes = [attribute0, attribute1]; >- const input0 = {stride: 20, attributeSet: attributes}; >- const inputs = [input0]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1.0; >- vertexBuffer0Float32Array[4] = 1.0; >- >- vertexBuffer0Float32Array[5] = -0.5; >- vertexBuffer0Float32Array[6] = 0.5; >- vertexBuffer0Float32Array[7] = 1.0; >- vertexBuffer0Float32Array[8] = 1.0; >- vertexBuffer0Float32Array[9] = 1.0; >- >- vertexBuffer0Float32Array[10] = 0.5; >- vertexBuffer0Float32Array[11] = -0.5; >- vertexBuffer0Float32Array[12] = 1.0; >- vertexBuffer0Float32Array[13] = 1.0; >- vertexBuffer0Float32Array[14] = 1.0; >- >- vertexBuffer0Float32Array[15] = 0.5; >- vertexBuffer0Float32Array[16] = 0.5; >- vertexBuffer0Float32Array[17] = 1.0; >- vertexBuffer0Float32Array[18] = 1.0; >- vertexBuffer0Float32Array[19] = 1.0; >- vertexBuffer0.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl.html b/LayoutTests/webgpu/whlsl.html >deleted file mode 100644 >index 13726de8a384bd63ea977fd065273efdbe1eeabb..0000000000000000000000000000000000000000 >--- a/LayoutTests/webgpu/whlsl.html >+++ /dev/null >@@ -1,119 +0,0 @@ >-<!DOCTYPE html> >-<html> >-<head> >-</head> >-<body> >-<canvas id="canvas" width="400" height="400"></canvas> >-<script> >-const shaderSource = ` >-vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position { >- return position; >-} >- >-fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 { >- return position; >-} >-`; >-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 attribute1 = {shaderLocation: 1, format: "float"}; >- const input0 = {stride: 16, attributeSet: [attribute0]}; >- const input1 = {stride: 4, attributeSet: [attribute1]}; >- const inputs = [input0, input1]; >- const vertexInput = {vertexBuffers: inputs}; >- >- const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >- const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >- const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >- const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >- >- const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >- const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >- >- const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >- const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >- const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >- vertexBuffer0Float32Array[0] = -0.5; >- vertexBuffer0Float32Array[1] = -0.5; >- vertexBuffer0Float32Array[2] = 1.0; >- vertexBuffer0Float32Array[3] = 1; >- vertexBuffer0Float32Array[4] = -0.5; >- vertexBuffer0Float32Array[5] = 0.5; >- vertexBuffer0Float32Array[6] = 1.0; >- vertexBuffer0Float32Array[7] = 1; >- vertexBuffer0Float32Array[8] = 0.5; >- vertexBuffer0Float32Array[9] = -0.5; >- vertexBuffer0Float32Array[10] = 1.0; >- vertexBuffer0Float32Array[11] = 1; >- vertexBuffer0Float32Array[12] = 0.5; >- vertexBuffer0Float32Array[13] = 0.5; >- vertexBuffer0Float32Array[14] = 1.0; >- vertexBuffer0Float32Array[15] = 1; >- vertexBuffer0.unmap(); >- >- const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >- 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; >- vertexBuffer1.unmap(); >- >- const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >- const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >- const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >- const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >- resourceBufferFloat32Array[0] = 1; >- resourceBuffer.unmap(); >- >- const bufferBinding = {buffer: resourceBuffer, size: 4}; >- const bindGroupBinding = {binding: 0, resource: bufferBinding}; >- const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >- const bindGroup = device.createBindGroup(bindGroupDescriptor); >- >- 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.setBindGroup(0, bindGroup); >- renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 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> >diff --git a/LayoutTests/webgpu/whlsl/propertyresolver/ander-abstract-lvalue.html b/LayoutTests/webgpu/whlsl/propertyresolver/ander-abstract-lvalue.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1dc7b490e6128aa21e85a50cdde42abb20f6f587 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/propertyresolver/ander-abstract-lvalue.html >@@ -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(0.5, 0.5, 0.5, 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> >diff --git a/LayoutTests/webgpu/whlsl/propertyresolver/getter.html b/LayoutTests/webgpu/whlsl/propertyresolver/getter.html >new file mode 100644 >index 0000000000000000000000000000000000000000..cc5cba018e5045afefdf51aa7d274a61ebc394f3 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/propertyresolver/getter.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/propertyresolver/setter-abstract-lvalue.html b/LayoutTests/webgpu/whlsl/propertyresolver/setter-abstract-lvalue.html >new file mode 100644 >index 0000000000000000000000000000000000000000..0ddc7b459c17fda29a1b1f758b79460008811d91 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/propertyresolver/setter-abstract-lvalue.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/propertyresolver/setter-lvalue.html b/LayoutTests/webgpu/whlsl/propertyresolver/setter-lvalue.html >new file mode 100644 >index 0000000000000000000000000000000000000000..9a9b4f29555bde124d99182beb3ab27da7be9c58 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/propertyresolver/setter-lvalue.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations-expected.html b/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations.html b/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations.html >new file mode 100644 >index 0000000000000000000000000000000000000000..b35e6c2cc251f4a3f61c86bc8a0a329cae200d7f >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-arbitrary-vertex-attribute-locations.html >@@ -0,0 +1,123 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(173), float shade : attribute(498)) { >+ VertexOut result; >+ result.position = position; >+ result.shade = shade; >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 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: 173, format: "float4"}; >+ const attribute1 = {shaderLocation: 498, format: "float", offset: 16}; >+ const input0 = {stride: 20, attributeSet: [attribute0, attribute1]}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 1.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 1.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 1.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 1.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check-expected.html b/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check.html b/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check.html >new file mode 100644 >index 0000000000000000000000000000000000000000..9507d6b2b6c2b769b0ed763916c0268ed713080e >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dereference-pointer-should-type-check.html >@@ -0,0 +1,129 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ thread float* ptr2 = &shade; >+ *ptr2 = shade; >+ >+ result.position = position; >+ result.shade = *ptr2; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 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", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 1.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 1.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 1.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 1.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum-expected.html b/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum.html b/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum.html >new file mode 100644 >index 0000000000000000000000000000000000000000..2f8edd3bd146d3aecc6603e6907f7cf4d948ac6a >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dont-crash-parsing-enum.html >@@ -0,0 +1,124 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+ >+enum DontCrash { >+ Value >+} >+ >+vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position { >+ return position; >+} >+ >+fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 { >+ return position; >+} >+`; >+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 attribute1 = {shaderLocation: 1, format: "float"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const input1 = {stride: 4, attributeSet: [attribute1]}; >+ const inputs = [input0, input1]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1; >+ vertexBuffer0Float32Array[4] = -0.5; >+ vertexBuffer0Float32Array[5] = 0.5; >+ vertexBuffer0Float32Array[6] = 1.0; >+ vertexBuffer0Float32Array[7] = 1; >+ vertexBuffer0Float32Array[8] = 0.5; >+ vertexBuffer0Float32Array[9] = -0.5; >+ vertexBuffer0Float32Array[10] = 1.0; >+ vertexBuffer0Float32Array[11] = 1; >+ vertexBuffer0Float32Array[12] = 0.5; >+ vertexBuffer0Float32Array[13] = 0.5; >+ vertexBuffer0Float32Array[14] = 1.0; >+ vertexBuffer0Float32Array[15] = 1; >+ vertexBuffer0.unmap(); >+ >+ const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ 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; >+ vertexBuffer1.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dot-expressions-expected.html b/LayoutTests/webgpu/whlsl/whlsl-dot-expressions-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dot-expressions-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-dot-expressions.html b/LayoutTests/webgpu/whlsl/whlsl-dot-expressions.html >new file mode 100644 >index 0000000000000000000000000000000000000000..00563226f11bdfcebeebff8b802fbff18ef9e687 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-dot-expressions.html >@@ -0,0 +1,124 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ result.position = position; >+ result.shade = shade; >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 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 attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 1.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 1.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 1.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 1.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-expected.html b/LayoutTests/webgpu/whlsl/whlsl-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue-expected.html b/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue-expected.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f417050f9a743f05e9006fc91ac64d502dadd633 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue-expected.html >@@ -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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue.html b/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f72ad54927e36359684282e8fbe26471de4d4eb8 >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl-nested-dot-expression-rvalue.html >@@ -0,0 +1,138 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+ >+struct Bar { >+ float shade; >+} >+struct Foo { >+ Bar bar; >+} >+ >+struct Wrapper { >+ Foo foo; >+} >+ >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ Wrapper wrapper; >+ wrapper.foo.bar.shade = shade; >+ VertexOut result; >+ result.position = position; >+ result.shade = wrapper.foo.bar.shade; >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 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 attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 1.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 1.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 1.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 1.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [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> >diff --git a/LayoutTests/webgpu/whlsl/whlsl.html b/LayoutTests/webgpu/whlsl/whlsl.html >new file mode 100644 >index 0000000000000000000000000000000000000000..13726de8a384bd63ea977fd065273efdbe1eeabb >--- /dev/null >+++ b/LayoutTests/webgpu/whlsl/whlsl.html >@@ -0,0 +1,119 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position { >+ return position; >+} >+ >+fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 { >+ return position; >+} >+`; >+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 attribute1 = {shaderLocation: 1, format: "float"}; >+ const input0 = {stride: 16, attributeSet: [attribute0]}; >+ const input1 = {stride: 4, attributeSet: [attribute1]}; >+ const inputs = [input0, input1]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1; >+ vertexBuffer0Float32Array[4] = -0.5; >+ vertexBuffer0Float32Array[5] = 0.5; >+ vertexBuffer0Float32Array[6] = 1.0; >+ vertexBuffer0Float32Array[7] = 1; >+ vertexBuffer0Float32Array[8] = 0.5; >+ vertexBuffer0Float32Array[9] = -0.5; >+ vertexBuffer0Float32Array[10] = 1.0; >+ vertexBuffer0Float32Array[11] = 1; >+ vertexBuffer0Float32Array[12] = 0.5; >+ vertexBuffer0Float32Array[13] = 0.5; >+ vertexBuffer0Float32Array[14] = 1.0; >+ vertexBuffer0Float32Array[15] = 1; >+ vertexBuffer0.unmap(); >+ >+ const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ 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; >+ vertexBuffer1.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ 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.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 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 198399
:
371002
|
371003
|
371042
|
371101
|
371110
|
371138
|
371139
|
371857
|
371872