LayoutTests/webgpu/whlsl.html

@@vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1
1010 return position;
1111}
1212
13 fragment float4 fragmentShader(float4 position : SV_Position, constant float[] theBuffer : register(b0)) : SV_Target 0 {
14  return float4(1.0, theBuffer[0], 1.0, 1.0);
 13fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 {
 14 return position;
1515}
1616`;
1717async function start() {

@@async function start() {
6969 const vertexBuffer1 = device.createBuffer(vertexBuffer1Descriptor);
7070 const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync();
7171 const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer);
72  vertexBuffer1Float32Array[0] = 1;
73  vertexBuffer1Float32Array[1] = 1;
74  vertexBuffer1Float32Array[2] = 1;
75  vertexBuffer1Float32Array[3] = 1;
 72 vertexBuffer1Descriptor[0] = 1;
 73 vertexBuffer1Descriptor[1] = 1;
 74 vertexBuffer1Descriptor[2] = 1;
 75 vertexBuffer1Descriptor[3] = 1;
7676 vertexBuffer1.unmap();
7777
7878 const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};

Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h

@@public:
9999 }
100100
101101 Expression& base() { return m_base; }
102  UniqueRef<Expression>& baseReference() { return m_base; }
103102 UniqueRef<Expression> takeBase() { return WTFMove(m_base); }
104103
105104private:

Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp

3232#include "WHLSLFunctionDefinition.h"
3333#include "WHLSLGatherEntryPointItems.h"
3434#include "WHLSLPipelineDescriptor.h"
35 #include "WHLSLReferenceType.h"
3635#include "WHLSLResourceSemantic.h"
3736#include "WHLSLStageInOutSemantic.h"
3837#include "WHLSLStructureDefinition.h"

@@EntryPointScaffolding::EntryPointScaffolding(AST::FunctionDefinition& functionDe
109108 for (size_t j = 0; j < m_layout[i].bindings.size(); ++j) {
110109 NamedBinding namedBinding;
111110 namedBinding.elementName = m_typeNamer.generateNextStructureElementName();
112  namedBinding.index = m_layout[i].bindings[j].internalName;
113  WTF::visit(WTF::makeVisitor([&](UniformBufferBinding& uniformBufferBinding) {
114  LengthInformation lengthInformation { m_typeNamer.generateNextStructureElementName(), m_generateNextVariableName(), uniformBufferBinding.lengthName };
115  namedBinding.lengthInformation = lengthInformation;
116  }, [&](SamplerBinding&) {
117  }, [&](TextureBinding&) {
118  }, [&](StorageBufferBinding& storageBufferBinding) {
119  LengthInformation lengthInformation { m_typeNamer.generateNextStructureElementName(), m_generateNextVariableName(), storageBufferBinding.lengthName };
120  namedBinding.lengthInformation = lengthInformation;
121  }), m_layout[i].bindings[j].binding);
 111 namedBinding.index = m_layout[i].bindings[j].name; // GPUBindGroupLayout::tryCreate() makes sure these don't collide.
122112 namedBindGroup.namedBindings.uncheckedAppend(WTFMove(namedBinding));
123113 }
124114 m_namedBindGroups.uncheckedAppend(WTFMove(namedBindGroup));

@@String EntryPointScaffolding::resourceHelperTypes()
147137 auto iterator = m_resourceMap.find(&m_layout[i].bindings[j]);
148138 if (iterator == m_resourceMap.end())
149139 continue;
150  auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType;
151  ASSERT(is<AST::ReferenceType>(unnamedType));
152  auto& referenceType = downcast<AST::ReferenceType>(unnamedType);
153  auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType());
154  auto addressSpace = toString(referenceType.addressSpace());
 140 auto mangledTypeName = m_typeNamer.mangledNameForType(*m_entryPointItems.inputs[iterator->value].unnamedType);
155141 auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
156142 auto index = m_namedBindGroups[i].namedBindings[j].index;
157  stringBuilder.append(makeString(" ", addressSpace, " ", mangledTypeName, "* ", elementName, " [[id(", index, ")]];\n"));
158  if (auto lengthInformation = m_namedBindGroups[i].namedBindings[j].lengthInformation)
159  stringBuilder.append(makeString(" uint2 ", lengthInformation->elementName, " [[id(", lengthInformation->index, ")]];\n"));
 143 stringBuilder.append(makeString(" ", mangledTypeName, ' ', elementName, " [[id(", index, ")]];\n"));
160144 }
161145 stringBuilder.append("};\n\n");
162146 }

@@String EntryPointScaffolding::unpackResourcesAndNamedBuiltIns()
273257 auto iterator = m_resourceMap.find(&m_layout[i].bindings[j]);
274258 if (iterator == m_resourceMap.end())
275259 continue;
276  if (m_namedBindGroups[i].namedBindings[j].lengthInformation) {
277  auto& path = m_entryPointItems.inputs[iterator->value].path;
278  auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
279  auto lengthElementName = m_namedBindGroups[i].namedBindings[j].lengthInformation->elementName;
280  auto lengthTemporaryName = m_namedBindGroups[i].namedBindings[j].lengthInformation->temporaryName;
281 
282  auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType;
283  ASSERT(is<AST::ReferenceType>(unnamedType));
284  auto& referenceType = downcast<AST::ReferenceType>(unnamedType);
285  auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType());
286 
287  stringBuilder.append(makeString("size_t ", lengthTemporaryName, " = ", variableName, '.', lengthElementName, ".x;\n"));
288  stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " << 32;\n"));
289  stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " | ", variableName, '.', lengthElementName, ".y;\n"));
290  stringBuilder.append(makeString(lengthTemporaryName, " = ", lengthTemporaryName, " / sizeof(", mangledTypeName, ");\n"));
291  stringBuilder.append(makeString("if (", lengthTemporaryName, " > 0xFFFFFFFF) ", lengthTemporaryName, " = 0xFFFFFFFF;\n"));
292  stringBuilder.append(makeString(mangledInputPath(path), " = { ", variableName, '.', elementName, ", static_cast<uint32_t>(", lengthTemporaryName, ") };\n"));
293  } else {
294  auto& path = m_entryPointItems.inputs[iterator->value].path;
295  auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
296  stringBuilder.append(makeString(mangledInputPath(path), " = ", variableName, '.', elementName, ";\n"));
297  }
 260 auto& path = m_entryPointItems.inputs[iterator->value].path;
 261 auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
 262 stringBuilder.append(makeString(mangledInputPath(path), " = ", variableName, '.', elementName, ";\n"));
298263 }
299264 }
300265

Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h

@@protected:
7777 Layout& m_layout;
7878 std::function<String()> m_generateNextVariableName;
7979
80  struct LengthInformation {
81  String elementName;
82  String temporaryName;
83  unsigned index;
84  };
8580 struct NamedBinding {
8681 String elementName;
8782 unsigned index;
88  Optional<LengthInformation> lengthInformation;
8983 };
9084 struct NamedBindGroup {
9185 String structName;

Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp

@@public:
117117 }
118118};
119119
120 static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(Lexer::Token origin, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics)
 120static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(AST::CallExpression& callExpression, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics)
121121{
122122 const bool isOperator = true;
123  auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(origin), firstArgument.addressSpace(), firstArgument.elementType().clone());
 123 auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(callExpression.origin()), firstArgument.addressSpace(), firstArgument.elementType().clone());
124124 AST::VariableDeclarations parameters;
125  parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt));
126  parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.uintType())), String(), WTF::nullopt, WTF::nullopt));
127  return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
 125 parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt));
 126 parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType())), String(), WTF::nullopt, WTF::nullopt));
 127 return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator&[]", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
128128}
129129
130 static AST::NativeFunctionDeclaration resolveWithOperatorLength(Lexer::Token origin, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics)
 130static AST::NativeFunctionDeclaration resolveWithOperatorLength(AST::CallExpression& callExpression, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics)
131131{
132132 const bool isOperator = true;
133  auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.uintType());
 133 auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType());
134134 AST::VariableDeclarations parameters;
135  parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt));
136  return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator.length", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
 135 parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), firstArgument.clone(), String(), WTF::nullopt, WTF::nullopt));
 136 return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator.length", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
137137}
138138
139 static AST::NativeFunctionDeclaration resolveWithReferenceComparator(Lexer::Token origin, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics)
 139static AST::NativeFunctionDeclaration resolveWithReferenceComparator(AST::CallExpression& callExpression, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics)
140140{
141141 const bool isOperator = true;
142  auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.boolType());
 142 auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.boolType());
143143 auto argumentType = firstArgument.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> UniqueRef<AST::UnnamedType> {
144144 return unnamedType->clone();
145145 }, [&](RefPtr<ResolvableTypeReference>&) -> UniqueRef<AST::UnnamedType> {

@@static AST::NativeFunctionDeclaration resolveWithReferenceComparator(Lexer::Toke
149149 // We encountered "null == null".
150150 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198162 This can probably be generalized, using the "preferred type" infrastructure used by generic literals
151151 ASSERT_NOT_REACHED();
152  return AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.intType());
 152 return AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.intType());
153153 }));
154154 }));
155155 AST::VariableDeclarations parameters;
156  parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), argumentType->clone(), String(), WTF::nullopt, WTF::nullopt));
157  parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt));
158  return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(origin), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
 156 parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), argumentType->clone(), String(), WTF::nullopt, WTF::nullopt));
 157 parameters.append(makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(callExpression.origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(WTFMove(argumentType)), String(), WTF::nullopt, WTF::nullopt));
 158 return AST::NativeFunctionDeclaration(AST::FunctionDeclaration(Lexer::Token(callExpression.origin()), AST::AttributeBlock(), WTF::nullopt, WTFMove(returnType), String("operator==", String::ConstructFromLiteral), WTFMove(parameters), WTF::nullopt, isOperator));
159159}
160160
161161enum class Acceptability {

@@enum class Acceptability {
164164 No
165165};
166166
167 static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const String& name, Lexer::Token origin, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics)
 167static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(AST::CallExpression& callExpression, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics)
168168{
169  if (name == "operator&[]" && types.size() == 2) {
 169 if (callExpression.name() == "operator&[]" && types.size() == 2) {
170170 auto* firstArgumentArrayRef = types[0].get().visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::ArrayReferenceType* {
171171 if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)))
172172 return &downcast<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType));

@@static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const Str
180180 return resolvableTypeReference->resolvableType().canResolve(intrinsics.uintType());
181181 }));
182182 if (firstArgumentArrayRef && secondArgumentIsUint)
183  return resolveWithOperatorAnderIndexer(origin, *firstArgumentArrayRef, intrinsics);
184  } else if (name == "operator.length" && types.size() == 1) {
 183 return resolveWithOperatorAnderIndexer(callExpression, *firstArgumentArrayRef, intrinsics);
 184 } else if (callExpression.name() == "operator.length" && types.size() == 1) {
185185 auto* firstArgumentReference = types[0].get().visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> AST::UnnamedType* {
186186 if (is<AST::ArrayReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)))
187187 return &unnamedType;

@@static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const Str
190190 return nullptr;
191191 }));
192192 if (firstArgumentReference)
193  return resolveWithOperatorLength(origin, *firstArgumentReference, intrinsics);
194  } else if (name == "operator==" && types.size() == 2) {
 193 return resolveWithOperatorLength(callExpression, *firstArgumentReference, intrinsics);
 194 } else if (callExpression.name() == "operator==" && types.size() == 2) {
195195 auto acceptability = [](ResolvingType& resolvingType) -> Acceptability {
196196 return resolvingType.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> Acceptability {
197197 return is<AST::ReferenceType>(static_cast<AST::UnnamedType&>(unnamedType)) ? Acceptability::Yes : Acceptability::No;

@@static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const Str
210210 || (leftAcceptability == Acceptability::Yes && rightAcceptability == Acceptability::Maybe))
211211 success = true;
212212 if (success)
213  return resolveWithReferenceComparator(origin, types[0].get(), types[1].get(), intrinsics);
 213 return resolveWithReferenceComparator(callExpression, types[0].get(), types[1].get(), intrinsics);
214214 }
215215 return WTF::nullopt;
216216}

@@void Checker::visit(AST::MakeArrayReferenceExpression& makeArrayReferenceExpress
969969 assignType(makeArrayReferenceExpression, makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(makeArrayReferenceExpression.origin()), *leftAddressSpace, leftValueType->clone()));
970970}
971971
972 static Optional<UniqueRef<AST::UnnamedType>> argumentTypeForAndOverload(AST::UnnamedType& baseType, AST::AddressSpace addressSpace)
973 {
974  auto& unifyNode = baseType.unifyNode();
975  if (is<AST::NamedType>(unifyNode)) {
976  auto& namedType = downcast<AST::NamedType>(unifyNode);
977  return { makeUniqueRef<AST::PointerType>(Lexer::Token(namedType.origin()), addressSpace, AST::TypeReference::wrap(Lexer::Token(namedType.origin()), namedType)) };
978  }
979 
980  ASSERT(is<AST::UnnamedType>(unifyNode));
981  auto& unnamedType = downcast<AST::UnnamedType>(unifyNode);
982 
983  if (is<AST::ArrayReferenceType>(unnamedType))
984  return unnamedType.clone();
985 
986  if (is<AST::ArrayType>(unnamedType))
987  return { makeUniqueRef<AST::ArrayReferenceType>(Lexer::Token(unnamedType.origin()), addressSpace, downcast<AST::ArrayType>(unnamedType).type().clone()) };
988 
989  if (is<AST::PointerType>(unnamedType))
990  return WTF::nullopt;
991 
992  return { makeUniqueRef<AST::PointerType>(Lexer::Token(unnamedType.origin()), addressSpace, unnamedType.clone()) };
993 }
994 
995972void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpression, ResolvingType* additionalArgumentType)
996973{
997974 auto baseInfo = recurseAndGetInfo(propertyAccessExpression.base());

@@void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpres
1015992 AST::UnnamedType* anderReturnType = nullptr;
1016993 auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace();
1017994 if (leftAddressSpace) {
1018  if (auto argumentTypeForAndOverload = WHLSL::argumentTypeForAndOverload(*baseUnnamedType, *leftAddressSpace)) {
1019  ResolvingType argumentType = { WTFMove(*argumentTypeForAndOverload) };
1020  Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { argumentType };
1021  if (additionalArgumentType)
1022  anderArgumentTypes.append(*additionalArgumentType);
1023  if ((anderFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes, nullptr)))
1024  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
1025  else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), anderArgumentTypes, m_intrinsics)) {
1026  m_program.append(WTFMove(*newFunction));
1027  anderFunction = &m_program.nativeFunctionDeclarations().last();
1028  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
1029  }
1030  }
 995 ResolvingType argumentType = { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), *leftAddressSpace, baseUnnamedType->get().clone()) };
 996 Vector<std::reference_wrapper<ResolvingType>> anderArgumentTypes { argumentType };
 997 if (additionalArgumentType)
 998 anderArgumentTypes.append(*additionalArgumentType);
 999 if ((anderFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes, nullptr)))
 1000 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
10311001 }
10321002
10331003 AST::FunctionDeclaration* threadAnderFunction = nullptr;
10341004 AST::UnnamedType* threadAnderReturnType = nullptr;
1035  if (auto argumentTypeForAndOverload = WHLSL::argumentTypeForAndOverload(*baseUnnamedType, AST::AddressSpace::Thread)) {
 1005 {
10361006 ResolvingType argumentType = { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, baseUnnamedType->get().clone()) };
10371007 Vector<std::reference_wrapper<ResolvingType>> threadAnderArgumentTypes { argumentType };
10381008 if (additionalArgumentType)
10391009 threadAnderArgumentTypes.append(*additionalArgumentType);
10401010 if ((threadAnderFunction = resolveFunctionOverloadImpl(propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes, nullptr)))
10411011 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
1042  else if (auto newFunction = resolveByInstantiation(propertyAccessExpression.anderFunctionName(), propertyAccessExpression.origin(), threadAnderArgumentTypes, m_intrinsics)) {
1043  m_program.append(WTFMove(*newFunction));
1044  threadAnderFunction = &m_program.nativeFunctionDeclarations().last();
1045  threadAnderReturnType = &downcast<AST::PointerType>(anderFunction->type()).elementType(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198164 Enforce the return of anders will always be a pointer
1046  }
10471012 }
10481013
10491014 if (leftAddressSpace && !anderFunction && !getterFunction) {

@@void Checker::visit(AST::CallExpression& callExpression)
14691434 ASSERT(callExpression.hasOverloads());
14701435 auto* function = resolveFunctionOverloadImpl(*callExpression.overloads(), types, callExpression.castReturnType());
14711436 if (!function) {
1472  if (auto newFunction = resolveByInstantiation(callExpression.name(), callExpression.origin(), types, m_intrinsics)) {
 1437 if (auto newFunction = resolveByInstantiation(callExpression, types, m_intrinsics)) {
14731438 m_program.append(WTFMove(*newFunction));
14741439 function = &m_program.nativeFunctionDeclarations().last();
14751440 }

Source/WebCore/Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h

@@enum class ShaderStage : uint8_t {
114114 Compute = 1 << 2
115115};
116116
117 struct UniformBufferBinding {
118  unsigned lengthName;
 117enum class BindingType : uint8_t {
 118 UniformBuffer,
 119 Sampler,
 120 Texture,
 121 StorageBuffer,
 122 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198168 Add the dynamic types
119123};
120124
121 struct SamplerBinding {
122 };
123 
124 struct TextureBinding {
125 };
126 
127 struct StorageBufferBinding {
128  unsigned lengthName;
129 };
130 
131 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198168 Add the dynamic types
132 
133125struct Binding {
134  using BindingDetails = Variant<UniformBufferBinding, SamplerBinding, TextureBinding, StorageBufferBinding>;
135126 OptionSet<ShaderStage> visibility;
136  BindingDetails binding;
137  unsigned internalName;
138  unsigned externalName;
 127 BindingType bindingType;
 128 unsigned name;
139129};
140130
141131struct BindGroup {

Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp

@@namespace WebCore {
5555
5656namespace WHLSL {
5757
58 static constexpr bool dumpASTBeforeEachPass = true;
 58static constexpr bool dumpASTBeforeEachPass = false;
5959static constexpr bool dumpASTAfterParsing = false;
6060static constexpr bool dumpASTAtEnd = true;
6161static constexpr bool alwaysDumpPassFailures = false;

@@static Optional<Program> prepareShared(String& whlslSource)
124124 RUN_PASS(check, program);
125125
126126 checkLiteralTypes(program);
127  dumpASTBetweenEachPassIfNeeded(program, "AST before resolveProperties");
128127 resolveProperties(program);
129  dumpASTBetweenEachPassIfNeeded(program, "AST after resolveProperties");
130128 findHighZombies(program);
131129 RUN_PASS(checkStatementBehavior, program);
132130 RUN_PASS(checkRecursion, program);

Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp

3535#include "WHLSLDotExpression.h"
3636#include "WHLSLFunctionDeclaration.h"
3737#include "WHLSLFunctionDefinition.h"
38 #include "WHLSLMakeArrayReferenceExpression.h"
3938#include "WHLSLMakePointerExpression.h"
4039#include "WHLSLPointerType.h"
4140#include "WHLSLReadModifyWriteExpression.h"

@@private:
5655 void visit(AST::AssignmentExpression&) override;
5756 void visit(AST::ReadModifyWriteExpression&) override;
5857
59  void simplifyRightValue(AST::PropertyAccessExpression&);
 58 bool simplifyRightValue(AST::PropertyAccessExpression&);
6059 bool simplifyAbstractLeftValue(AST::AssignmentExpression&, AST::DotExpression&, UniqueRef<AST::Expression>&& right);
6160 void simplifyLeftValue(AST::Expression&);
6261

@@private:
6665void PropertyResolver::visit(AST::DotExpression& dotExpression)
6766{
6867 // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value.
69  simplifyRightValue(dotExpression);
 68 if (!simplifyRightValue(dotExpression))
 69 setError();
7070}
7171
7272void PropertyResolver::visit(AST::IndexExpression& indexExpression)
7373{
7474 checkErrorAndVisit(indexExpression.indexExpression());
7575 // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value.
76  simplifyRightValue(indexExpression);
 76 if (!simplifyRightValue(indexExpression))
 77 setError();
7778}
7879
7980void PropertyResolver::visit(AST::FunctionDefinition& functionDefinition)

@@void PropertyResolver::visit(AST::FunctionDefinition& functionDefinition)
8384 functionDefinition.block().statements().insert(0, makeUniqueRef<AST::VariableDeclarationsStatement>(Lexer::Token(m_variableDeclarations[0]->origin()), WTFMove(m_variableDeclarations)));
8485}
8586
86 enum class WhichAnder {
87  ThreadAnder,
88  NonThreadAnder
89 };
90 
91 struct AnderCallArgumentResult {
92  UniqueRef<AST::Expression> expression;
93  Optional<UniqueRef<AST::VariableDeclaration>> variableDeclaration;
94  WhichAnder whichAnder;
95 };
96 
97 template <typename ExpressionConstructor, typename TypeConstructor>
98 static Optional<AnderCallArgumentResult> wrapAnderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction)
99 {
100  if (auto addressSpace = expression->typeAnnotation().leftAddressSpace()) {
101  if (!anderFunction)
102  return WTF::nullopt;
103  auto origin = expression->origin();
104  auto baseType = expression->resolvedType().clone();
105  auto makeArrayReference = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(expression));
106  makeArrayReference->setType(makeUniqueRef<TypeConstructor>(WTFMove(origin), *addressSpace, WTFMove(baseType)));
107  makeArrayReference->setTypeAnnotation(AST::RightValue());
108  return {{ WTFMove(makeArrayReference), WTF::nullopt, WhichAnder::NonThreadAnder }};
109  }
110  if (threadAnderFunction) {
111  auto origin = expression->origin();
112  auto baseType = expression->resolvedType().clone();
113  auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), baseType->clone(), String(), WTF::nullopt, WTF::nullopt);
114 
115  auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
116  variableReference1->setType(baseType->clone());
117  variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
118 
119  auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), WTFMove(expression));
120  assignmentExpression->setType(baseType->clone());
121  assignmentExpression->setTypeAnnotation(AST::RightValue());
122 
123  auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
124  variableReference2->setType(baseType->clone());
125  variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
126 
127  auto expression = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(variableReference2));
128  auto resultType = makeUniqueRef<TypeConstructor>(Lexer::Token(origin), AST::AddressSpace::Thread, WTFMove(baseType));
129  expression->setType(resultType->clone());
130  expression->setTypeAnnotation(AST::RightValue());
131 
132  Vector<UniqueRef<AST::Expression>> expressions;
133  expressions.append(WTFMove(assignmentExpression));
134  expressions.append(WTFMove(expression));
135  auto commaExpression = makeUniqueRef<AST::CommaExpression>(WTFMove(origin), WTFMove(expressions));
136  commaExpression->setType(WTFMove(resultType));
137  commaExpression->setTypeAnnotation(AST::RightValue());
138  return {{ WTFMove(commaExpression), { WTFMove(variableDeclaration) }, WhichAnder::ThreadAnder}};
139  }
140  return WTF::nullopt;
141 }
142 
143 static Optional<AnderCallArgumentResult> anderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction)
144 {
145  auto& unifyNode = expression->resolvedType().unifyNode();
146  if (is<AST::UnnamedType>(unifyNode)) {
147  auto& unnamedType = downcast<AST::UnnamedType>(unifyNode);
148  ASSERT(!is<AST::PointerType>(unnamedType));
149  if (is<AST::ArrayReferenceType>(unnamedType))
150  return {{ WTFMove(expression), WTF::nullopt, WhichAnder::NonThreadAnder }};
151  if (is<AST::ArrayType>(unnamedType))
152  return wrapAnderCallArgument<AST::MakeArrayReferenceExpression, AST::ArrayReferenceType>(expression, anderFunction, threadAnderFunction);
153  }
154  return wrapAnderCallArgument<AST::MakePointerExpression, AST::PointerType>(expression, anderFunction, threadAnderFunction);
155 }
156 
157 static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable)
 87static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory, AST::VariableDeclaration* indexVariable)
15888{
15989 if (relevantAnder) {
16090 // *operator&.foo(&v) = newValue
161  auto leftValue = leftValueFactory();
162  auto argument = anderCallArgument(leftValue, true, true);
163  ASSERT(argument);
164  ASSERT(!argument->variableDeclaration);
165  ASSERT(argument->whichAnder == WhichAnder::NonThreadAnder);
16691 Vector<UniqueRef<AST::Expression>> arguments;
167  arguments.append(WTFMove(argument->expression));
 92 arguments.append(pointerToLeftValueFactory());
16893 if (indexVariable) {
16994 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*indexVariable));
17095 ASSERT(indexVariable->type());

@@static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpres
215140 return UniqueRef<AST::Expression>(WTFMove(assignmentExpression));
216141}
217142
218 static Optional<UniqueRef<AST::Expression>> getterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable)
 143static Optional<UniqueRef<AST::Expression>> getterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, const std::function<UniqueRef<AST::Expression>()>& pointerToLeftValueFactory, AST::VariableDeclaration* indexVariable)
219144{
220145 if (relevantAnder) {
221146 // *operator&.foo(&v)
222  auto leftValue = leftValueFactory();
223  auto argument = anderCallArgument(leftValue, true, true);
224  ASSERT(argument);
225  ASSERT(!argument->variableDeclaration);
226  ASSERT(argument->whichAnder == WhichAnder::NonThreadAnder);
227147 Vector<UniqueRef<AST::Expression>> arguments;
228  arguments.append(WTFMove(argument->expression));
 148 arguments.append(pointerToLeftValueFactory());
229149 if (indexVariable) {
230150 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*indexVariable));
231151 ASSERT(indexVariable->type());

@@static Optional<UniqueRef<AST::Expression>> getterCall(AST::PropertyAccessExpres
248168
249169 // operator.foo(v)
250170 ASSERT(propertyAccessExpression.getterFunction());
251 
 171
252172 Vector<UniqueRef<AST::Expression>> arguments;
253173 arguments.append(leftValueFactory());
254174 if (indexVariable) {

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
378298 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
379299 return variableReference;
380300 }
381 
 301
382302 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
383303 ASSERT(pointerVariable->type());
384304 variableReference->setType(pointerVariable->type()->clone());

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
390310 dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() });
391311 return dereferenceExpression;
392312 };
 313 auto pointerToPreviousLeftValue = [&]() -> UniqueRef<AST::Expression> {
 314 if (previous) {
 315 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*previous));
 316 ASSERT(previous->type());
 317 variableReference->setType(previous->type()->clone());
 318 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
 319
 320 auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference));
 321 ASSERT(previous->type());
 322 makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone()));
 323 makePointerExpression->setTypeAnnotation(AST::RightValue());
 324 return makePointerExpression;
 325 }
 326
 327 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
 328 ASSERT(pointerVariable->type());
 329 variableReference->setType(pointerVariable->type()->clone());
 330 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
 331 return variableReference;
 332 };
393333 auto appendIndexAssignment = [&](AST::PropertyAccessExpression& propertyAccessExpression, Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable) {
394334 if (!indexVariable)
395335 return;

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
415355 appendIndexAssignment(propertyAccessExpression, indexVariable);
416356
417357 AST::FunctionDeclaration* relevantAnder = i == chain.size() - 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction();
418  auto callExpression = getterCall(propertyAccessExpression, relevantAnder, previousLeftValue, indexVariable ? &*indexVariable : nullptr);
 358 auto callExpression = getterCall(propertyAccessExpression, relevantAnder, previousLeftValue, pointerToPreviousLeftValue, indexVariable ? &*indexVariable : nullptr);
419359
420360 if (!callExpression)
421361 return WTF::nullopt;

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
430370 assignmentExpression->setTypeAnnotation(AST::RightValue());
431371
432372 expressions.append(WTFMove(assignmentExpression));
433 
 373
434374 previous = &variableDeclaration;
435375 }
436376 appendIndexAssignment(chain[0], indexVariables[0]);
437377 AST::FunctionDeclaration* relevantAnder = chain.size() == 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction();
438  auto lastGetterCallExpression = getterCall(chain[0], relevantAnder, previousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr);
 378 auto lastGetterCallExpression = getterCall(chain[0], relevantAnder, previousLeftValue, pointerToPreviousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr);
439379
440380 // Step 3:
441381 auto modificationResult = modification(WTFMove(lastGetterCallExpression));

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
458398 variableReference->setType(variableDeclaration.type()->clone());
459399 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
460400 return variableReference;
 401 }, [&]() -> UniqueRef<AST::Expression> {
 402 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
 403 ASSERT(variableDeclaration.type());
 404 variableReference->setType(variableDeclaration.type()->clone());
 405 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
 406
 407 auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference));
 408 ASSERT(variableDeclaration.type());
 409 makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone()));
 410 makePointerExpression->setTypeAnnotation(AST::RightValue());
 411 return makePointerExpression;
461412 }, indexVariable ? &*indexVariable : nullptr);
462413
463414 if (!assignmentExpression)

@@static Optional<ModifyResult> modify(AST::PropertyAccessExpression& propertyAcce
485436 dereferenceExpression->setType(downcast<AST::PointerType>(*pointerVariable->type()).elementType().clone());
486437 dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() });
487438 return dereferenceExpression;
 439 }, [&]() -> UniqueRef<AST::Expression> {
 440 auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
 441 ASSERT(pointerVariable->type());
 442 variableReference->setType(pointerVariable->type()->clone());
 443 variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
 444 return variableReference;
488445 }, indexVariables[indexVariables.size() - 1] ? &*(indexVariables[indexVariables.size() - 1]) : nullptr);
489446
490447 if (!assignmentExpression)

@@void PropertyResolver::visit(AST::ReadModifyWriteExpression& readModifyWriteExpr
708665 m_variableDeclarations.append(WTFMove(newVariableDeclaration));
709666}
710667
711 static Optional<AnderCallArgumentResult> anderCallArgument(AST::PropertyAccessExpression& propertyAccessExpression)
712 {
713  return anderCallArgument(propertyAccessExpression.baseReference(), propertyAccessExpression.anderFunction(), propertyAccessExpression.threadAnderFunction());
714 }
715 
716 void PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression)
 668bool PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression)
717669{
718670 Lexer::Token origin = propertyAccessExpression.origin();
719671
720672 checkErrorAndVisit(propertyAccessExpression.base());
721673
722  if (auto argument = anderCallArgument(propertyAccessExpression)) {
723  auto* anderFunction = argument->whichAnder == WhichAnder::ThreadAnder ? propertyAccessExpression.threadAnderFunction() : propertyAccessExpression.anderFunction();
724  ASSERT(anderFunction);
725  auto origin = propertyAccessExpression.origin();
 674 auto& base = propertyAccessExpression.base();
 675 if (auto leftAddressSpace = base.typeAnnotation().leftAddressSpace()) {
 676 if (auto* anderFunction = propertyAccessExpression.anderFunction()) {
 677 auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.takeBase());
 678 makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), *leftAddressSpace, base.resolvedType().clone()));
 679 makePointerExpression->setTypeAnnotation(AST::RightValue());
 680
 681 Vector<UniqueRef<AST::Expression>> arguments;
 682 arguments.append(WTFMove(makePointerExpression));
 683 if (is<AST::IndexExpression>(propertyAccessExpression))
 684 arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
 685 auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments));
 686 callExpression->setType(anderFunction->type().clone());
 687 callExpression->setTypeAnnotation(AST::RightValue());
 688 callExpression->setFunction(*anderFunction);
 689
 690 auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression));
 691 dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone());
 692 dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() });
 693 return true;
 694 }
 695 }
 696
 697 if (propertyAccessExpression.getterFunction()) {
 698 auto& getterFunction = *propertyAccessExpression.getterFunction();
726699 Vector<UniqueRef<AST::Expression>> arguments;
727  arguments.append(WTFMove(argument->expression));
 700 arguments.append(propertyAccessExpression.takeBase());
728701 if (is<AST::IndexExpression>(propertyAccessExpression))
729702 arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
730  auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments));
731  callExpression->setType(anderFunction->type().clone());
 703 auto* callExpression = AST::replaceWith<AST::CallExpression>(propertyAccessExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments));
 704 callExpression->setFunction(getterFunction);
 705 callExpression->setType(getterFunction.type().clone());
732706 callExpression->setTypeAnnotation(AST::RightValue());
733  callExpression->setFunction(*anderFunction);
 707 return true;
 708 }
734709
735  auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression));
736  dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone());
737  dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() });
 710 // 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.
 711 // This is effectively inlining the functions the spec says are generated.
 712 ASSERT(propertyAccessExpression.threadAnderFunction());
 713 auto* threadAnderFunction = propertyAccessExpression.threadAnderFunction();
738714
739  if (auto& variableDeclaration = argument->variableDeclaration)
740  m_variableDeclarations.append(WTFMove(*variableDeclaration));
 715 auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), base.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt);
741716
742  return;
743  }
 717 auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
 718 variableReference1->setType(base.resolvedType().clone());
 719 variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
 720
 721 auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), propertyAccessExpression.takeBase());
 722 assignmentExpression->setType(base.resolvedType().clone());
 723 assignmentExpression->setTypeAnnotation(AST::RightValue());
 724
 725 auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
 726 variableReference2->setType(base.resolvedType().clone());
 727 variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
 728
 729 auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), WTFMove(variableReference2));
 730 makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), AST::AddressSpace::Thread, base.resolvedType().clone()));
 731 makePointerExpression->setTypeAnnotation(AST::RightValue());
744732
745  ASSERT(propertyAccessExpression.getterFunction());
746  auto& getterFunction = *propertyAccessExpression.getterFunction();
747733 Vector<UniqueRef<AST::Expression>> arguments;
748  arguments.append(propertyAccessExpression.takeBase());
 734 arguments.append(WTFMove(makePointerExpression));
749735 if (is<AST::IndexExpression>(propertyAccessExpression))
750736 arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
751  auto* callExpression = AST::replaceWith<AST::CallExpression>(propertyAccessExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments));
752  callExpression->setFunction(getterFunction);
753  callExpression->setType(getterFunction.type().clone());
 737 auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(threadAnderFunction->name()), WTFMove(arguments));
 738 callExpression->setType(threadAnderFunction->type().clone());
754739 callExpression->setTypeAnnotation(AST::RightValue());
 740 callExpression->setFunction(*threadAnderFunction);
 741
 742 auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(WTFMove(origin), WTFMove(callExpression));
 743 dereferenceExpression->setType(downcast<AST::PointerType>(threadAnderFunction->type()).elementType().clone());
 744 dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
 745
 746 Vector<UniqueRef<AST::Expression>> expressions;
 747 expressions.append(WTFMove(assignmentExpression));
 748 expressions.append(WTFMove(dereferenceExpression));
 749 auto* commaExpression = AST::replaceWith<AST::CommaExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(expressions));
 750 commaExpression->setType(downcast<AST::PointerType>(threadAnderFunction->type()).elementType().clone());
 751 commaExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
 752
 753 m_variableDeclarations.append(WTFMove(variableDeclaration));
 754 return true;
 755
755756}
756757
757758class LeftValueSimplifier : public Visitor {

@@void LeftValueSimplifier::finishVisiting(AST::PropertyAccessExpression& property
770771
771772 Lexer::Token origin = propertyAccessExpression.origin();
772773 auto* anderFunction = propertyAccessExpression.anderFunction();
773 
774  auto argument = anderCallArgument(propertyAccessExpression);
775  ASSERT(argument);
776  ASSERT(!argument->variableDeclaration);
777  ASSERT(argument->whichAnder == WhichAnder::NonThreadAnder);
 774 auto& base = propertyAccessExpression.base();
 775 auto leftAddressSpace = *propertyAccessExpression.base().typeAnnotation().leftAddressSpace();
 776 auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.takeBase());
 777 makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), leftAddressSpace, base.resolvedType().clone()));
 778 makePointerExpression->setTypeAnnotation(AST::RightValue());
778779
779780 Vector<UniqueRef<AST::Expression>> arguments;
780  arguments.append(WTFMove(argument->expression));
 781 arguments.append(WTFMove(makePointerExpression));
781782 if (is<AST::IndexExpression>(propertyAccessExpression))
782783 arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
783784 auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments));

Source/WebCore/Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp

@@static AST::FunctionDefinition* findEntryPoint(Vector<UniqueRef<AST::FunctionDef
5555 return &*iterator;
5656};
5757
58 static bool matchMode(Binding::BindingDetails bindingType, AST::ResourceSemantic::Mode mode)
 58static bool matchMode(BindingType bindingType, AST::ResourceSemantic::Mode mode)
5959{
60  return WTF::visit(WTF::makeVisitor([&](UniformBufferBinding) -> bool {
 60 switch (bindingType) {
 61 case BindingType::UniformBuffer:
6162 return mode == AST::ResourceSemantic::Mode::Buffer;
62  }, [&](SamplerBinding) -> bool {
 63 case BindingType::Sampler:
6364 return mode == AST::ResourceSemantic::Mode::Sampler;
64  }, [&](TextureBinding) -> bool {
 65 case BindingType::Texture:
6566 return mode == AST::ResourceSemantic::Mode::Texture;
66  }, [&](StorageBufferBinding) -> bool {
 67 default:
 68 ASSERT(bindingType == BindingType::StorageBuffer);
6769 return mode == AST::ResourceSemantic::Mode::UnorderedAccessView;
68  }), bindingType);
 70 }
6971}
7072
7173static Optional<HashMap<Binding*, size_t>> matchResources(Vector<EntryPointItem>& entryPointItems, Layout& layout, ShaderStage shaderStage)

@@static Optional<HashMap<Binding*, size_t>> matchResources(Vector<EntryPointItem>
8587 if (!WTF::holds_alternative<AST::ResourceSemantic>(semantic))
8688 continue;
8789 auto& resourceSemantic = WTF::get<AST::ResourceSemantic>(semantic);
88  if (!matchMode(binding.binding, resourceSemantic.mode()))
 90 if (!matchMode(binding.bindingType, resourceSemantic.mode()))
8991 continue;
90  if (binding.externalName != resourceSemantic.index())
 92 if (binding.name != resourceSemantic.index())
9193 continue;
9294 if (space != resourceSemantic.space())
9395 continue;

Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp

@@Optional<GPUBindGroupDescriptor> WebGPUBindGroupDescriptor::tryCreateGPUBindGrou
111111 if (!buffer)
112112 return WTF::nullopt;
113113
114  if (!validateBufferBindingType(buffer, layoutBinding.externalBinding, functionName))
 114 if (!validateBufferBindingType(buffer, layoutBinding, functionName))
115115 return WTF::nullopt;
116116
117117 return static_cast<GPUBindingResource>(GPUBufferBinding { makeRef(*buffer), bufferBinding.offset, bufferBinding.size });

@@Optional<GPUBindGroupDescriptor> WebGPUBindGroupDescriptor::tryCreateGPUBindGrou
119119
120120 auto bindingResource = WTF::visit(bindingResourceVisitor, binding.resource);
121121 if (!bindingResource) {
122  LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.externalBinding.binding);
 122 LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.binding);
123123 return WTF::nullopt;
124124 }
125125

Source/WebCore/platform/graphics/gpu/GPUBindGroupLayout.h

3333#include <wtf/RefCounted.h>
3434#include <wtf/RefPtr.h>
3535#include <wtf/RetainPtr.h>
36 #include <wtf/Variant.h>
3736
3837#if USE(METAL)
3938OBJC_PROTOCOL(MTLArgumentEncoder);

@@class GPUBindGroupLayout : public RefCounted<GPUBindGroupLayout> {
4847public:
4948 static RefPtr<GPUBindGroupLayout> tryCreate(const GPUDevice&, const GPUBindGroupLayoutDescriptor&);
5049
51  struct UniformBuffer {
52  unsigned internalLengthName;
53  };
54 
55  struct DynamicUniformBuffer {
56  unsigned internalLengthName;
57  };
58 
59  struct Sampler {
60  };
61 
62  struct SampledTexture {
63  };
64 
65  struct StorageBuffer {
66  unsigned internalLengthName;
67  };
68 
69  struct DynamicStorageBuffer {
70  unsigned internalLengthName;
71  };
72 
73  using InternalBindingDetails = Variant<UniformBuffer, DynamicUniformBuffer, Sampler, SampledTexture, StorageBuffer, DynamicStorageBuffer>;
74 
75  struct Binding {
76  GPUBindGroupLayoutBinding externalBinding;
77  unsigned internalName;
78  InternalBindingDetails internalBindingDetails;
79  };
80 
81  using BindingsMapType = HashMap<uint64_t, Binding, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
 50 using BindingsMapType = HashMap<uint64_t, GPUBindGroupLayoutBinding, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
8251 const BindingsMapType& bindingsMap() const { return m_bindingsMap; }
8352#if USE(METAL)
8453 MTLArgumentEncoder *vertexEncoder() const { return m_vertexEncoder.get(); }

Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm

@@static RetainPtr<MTLArgumentEncoder> tryCreateMtlArgumentEncoder(const GPUDevice
7777 return encoder;
7878};
7979
80 static RetainPtr<MTLArgumentDescriptor> argumentDescriptor(MTLDataType dataType, NSUInteger index)
81 {
82  RetainPtr<MTLArgumentDescriptor> mtlArgument;
83  BEGIN_BLOCK_OBJC_EXCEPTIONS;
84  mtlArgument = adoptNS([MTLArgumentDescriptor new]);
85  END_BLOCK_OBJC_EXCEPTIONS;
86 
87  [mtlArgument.get() setDataType:dataType];
88  [mtlArgument.get() setIndex:index];
89  return mtlArgument;
90 }
91 
9280RefPtr<GPUBindGroupLayout> GPUBindGroupLayout::tryCreate(const GPUDevice& device, const GPUBindGroupLayoutDescriptor& descriptor)
9381{
9482 if (!device.platformDevice()) {

@@RefPtr<GPUBindGroupLayout> GPUBindGroupLayout::tryCreate(const GPUDevice& device
9987 ArgumentArray vertexArgsArray, fragmentArgsArray, computeArgsArray;
10088 BindingsMapType bindingsMap;
10189
102  unsigned internalName = 0;
103  unsigned internalLengthBase = descriptor.bindings.size();
10490 for (const auto& binding : descriptor.bindings) {
105  Optional<unsigned> extraIndex;
106  auto internalDetails = ([&]() -> GPUBindGroupLayout::InternalBindingDetails {
107  switch (binding.type) {
108  case GPUBindingType::UniformBuffer:
109  extraIndex = internalLengthBase++;
110  return GPUBindGroupLayout::UniformBuffer { *extraIndex };
111  case GPUBindingType::DynamicUniformBuffer:
112  extraIndex = internalLengthBase++;
113  return GPUBindGroupLayout::DynamicUniformBuffer { *extraIndex };
114  case GPUBindingType::Sampler:
115  return GPUBindGroupLayout::Sampler { };
116  case GPUBindingType::SampledTexture:
117  return GPUBindGroupLayout::SampledTexture { };
118  case GPUBindingType::StorageBuffer:
119  extraIndex = internalLengthBase++;
120  return GPUBindGroupLayout::StorageBuffer { *extraIndex };
121  default:
122  ASSERT(binding.type == GPUBindingType::DynamicStorageBuffer);
123  extraIndex = internalLengthBase++;
124  return GPUBindGroupLayout::DynamicStorageBuffer { *extraIndex };
125  }
126  })();
127  Binding bindingDetails = { binding, internalName++, WTFMove(internalDetails) };
128  if (!bindingsMap.add(binding.binding, bindingDetails)) {
 91 if (!bindingsMap.add(binding.binding, binding)) {
12992 LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Duplicate binding %u found in GPUBindGroupLayoutDescriptor!", binding.binding);
13093 return nullptr;
13194 }
13295
133  RetainPtr<MTLArgumentDescriptor> mtlArgument = argumentDescriptor(MTLDataTypeForBindingType(binding.type), bindingDetails.internalName);
 96 RetainPtr<MTLArgumentDescriptor> mtlArgument;
13497
 98 BEGIN_BLOCK_OBJC_EXCEPTIONS;
 99 mtlArgument = adoptNS([MTLArgumentDescriptor new]);
 100 END_BLOCK_OBJC_EXCEPTIONS;
135101 if (!mtlArgument) {
136102 LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Unable to create MTLArgumentDescriptor for binding %u!", binding.binding);
137103 return nullptr;
138104 }
139105
140  auto addIndices = [&](ArgumentArray& array) -> bool {
141  appendArgumentToArray(array, mtlArgument);
142  if (extraIndex) {
143  RetainPtr<MTLArgumentDescriptor> mtlArgument = argumentDescriptor(MTLDataTypeUInt2, *extraIndex);
144  if (!mtlArgument) {
145  LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Unable to create MTLArgumentDescriptor for binding %u!", binding.binding);
146  return false;
147  }
148  appendArgumentToArray(array, mtlArgument);
149  }
150  return true;
151  };
152  if ((binding.visibility & GPUShaderStageBit::Flags::Vertex) && !addIndices(vertexArgsArray))
153  return nullptr;
154  if ((binding.visibility & GPUShaderStageBit::Flags::Fragment) && !addIndices(fragmentArgsArray))
155  return nullptr;
156  if ((binding.visibility & GPUShaderStageBit::Flags::Compute) && !addIndices(computeArgsArray))
157  return nullptr;
 106 [mtlArgument setDataType:MTLDataTypeForBindingType(binding.type)];
 107 [mtlArgument setIndex:binding.binding];
 108
 109 if (binding.visibility & GPUShaderStageBit::Flags::Vertex)
 110 appendArgumentToArray(vertexArgsArray, mtlArgument);
 111 if (binding.visibility & GPUShaderStageBit::Flags::Fragment)
 112 appendArgumentToArray(fragmentArgsArray, mtlArgument);
 113 if (binding.visibility & GPUShaderStageBit::Flags::Compute)
 114 appendArgumentToArray(computeArgsArray, mtlArgument);
158115 }
159116
160117 RetainPtr<MTLArgumentEncoder> vertex, fragment, compute;
161118
162  if (vertexArgsArray && !(vertex = tryCreateMtlArgumentEncoder(device, vertexArgsArray)))
163  return nullptr;
164  if (fragmentArgsArray && !(fragment = tryCreateMtlArgumentEncoder(device, fragmentArgsArray)))
165  return nullptr;
166  if (computeArgsArray && !(compute = tryCreateMtlArgumentEncoder(device, computeArgsArray)))
167  return nullptr;
 119 if (vertexArgsArray) {
 120 if (!(vertex = tryCreateMtlArgumentEncoder(device, vertexArgsArray)))
 121 return nullptr;
 122 }
 123 if (fragmentArgsArray) {
 124 if (!(fragment = tryCreateMtlArgumentEncoder(device, fragmentArgsArray)))
 125 return nullptr;
 126 }
 127 if (computeArgsArray) {
 128 if (!(compute = tryCreateMtlArgumentEncoder(device, computeArgsArray)))
 129 return nullptr;
 130 }
168131
169132 return adoptRef(new GPUBindGroupLayout(WTFMove(bindingsMap), WTFMove(vertex), WTFMove(fragment), WTFMove(compute)));
170133}

Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm

@@static Optional<GPUBufferBinding> tryGetResourceAsBufferBinding(const GPUBinding
7272 return GPUBufferBinding { bufferBinding.buffer.copyRef(), bufferBinding.offset, bufferBinding.size };
7373}
7474
75 static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned name, unsigned lengthName)
 75static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned index)
7676{
7777 ASSERT(argumentEncoder && bufferBinding.buffer->platformBuffer());
7878
7979 BEGIN_BLOCK_OBJC_EXCEPTIONS;
8080 // Bounds check when converting GPUBufferBinding ensures that NSUInteger cast of uint64_t offset is safe.
81  [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:static_cast<NSUInteger>(bufferBinding.offset) atIndex:name];
82  void* lengthPointer = [argumentEncoder constantDataAtIndex:lengthName];
83  memcpy(lengthPointer, &bufferBinding.size, sizeof(uint64_t));
 81 [argumentEncoder setBuffer:bufferBinding.buffer->platformBuffer() offset:static_cast<NSUInteger>(bufferBinding.offset) atIndex:index];
8482 END_BLOCK_OBJC_EXCEPTIONS;
8583}
8684

@@RefPtr<GPUBindGroup> GPUBindGroup::tryCreate(const GPUBindGroupDescriptor& descr
173171 return nullptr;
174172 }
175173 auto layoutBinding = layoutIterator->value;
176  if (layoutBinding.externalBinding.visibility == GPUShaderStageBit::Flags::None)
 174 if (layoutBinding.visibility == GPUShaderStageBit::Flags::None)
177175 continue;
178176
179  bool isForVertex = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Vertex;
180  bool isForFragment = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Fragment;
181  bool isForCompute = layoutBinding.externalBinding.visibility & GPUShaderStageBit::Flags::Compute;
 177 bool isForVertex = layoutBinding.visibility & GPUShaderStageBit::Flags::Vertex;
 178 bool isForFragment = layoutBinding.visibility & GPUShaderStageBit::Flags::Fragment;
 179 bool isForCompute = layoutBinding.visibility & GPUShaderStageBit::Flags::Compute;
182180
183181 if (isForVertex && !vertexEncoder) {
184182 LOG(WebGPU, "%s: No vertex argument encoder found for binding %u!", functionName, index);

@@RefPtr<GPUBindGroup> GPUBindGroup::tryCreate(const GPUBindGroupDescriptor& descr
193191 return nullptr;
194192 }
195193
196  auto handleBuffer = [&](unsigned internalLengthName) -> bool {
 194 switch (layoutBinding.type) {
 195 // FIXME: Support more resource types.
 196 // FIXME: We could avoid this ugly switch-on-type using virtual functions if GPUBindingResource is refactored as a base class rather than a Variant.
 197 case GPUBindingType::UniformBuffer:
 198 case GPUBindingType::StorageBuffer: {
197199 auto bufferResource = tryGetResourceAsBufferBinding(resourceBinding.resource, functionName);
198200 if (!bufferResource)
199  return false;
 201 return nullptr;
200202 if (isForVertex)
201  setBufferOnEncoder(vertexEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
 203 setBufferOnEncoder(vertexEncoder, *bufferResource, index);
202204 if (isForFragment)
203  setBufferOnEncoder(fragmentEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
 205 setBufferOnEncoder(fragmentEncoder, *bufferResource, index);
204206 if (isForCompute)
205  setBufferOnEncoder(computeEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
 207 setBufferOnEncoder(computeEncoder, *bufferResource, index);
206208 boundBuffers.append(bufferResource->buffer.copyRef());
207  return true;
208  };
209 
210  auto success = WTF::visit(WTF::makeVisitor([&](GPUBindGroupLayout::UniformBuffer& uniformBuffer) -> bool {
211  return handleBuffer(uniformBuffer.internalLengthName);
212  }, [&](GPUBindGroupLayout::DynamicUniformBuffer& dynamicUniformBuffer) -> bool {
213  return handleBuffer(dynamicUniformBuffer.internalLengthName);
214  }, [&](GPUBindGroupLayout::Sampler&) -> bool {
 209 break;
 210 }
 211 case GPUBindingType::Sampler: {
215212 auto samplerState = tryGetResourceAsMtlSampler(resourceBinding.resource, functionName);
216213 if (!samplerState)
217  return false;
 214 return nullptr;
218215 if (isForVertex)
219216 setSamplerOnEncoder(vertexEncoder, samplerState, index);
220217 if (isForFragment)
221218 setSamplerOnEncoder(fragmentEncoder, samplerState, index);
222219 if (isForCompute)
223220 setSamplerOnEncoder(computeEncoder, samplerState, index);
224  return true;
225  }, [&](GPUBindGroupLayout::SampledTexture&) -> bool {
 221 break;
 222 }
 223 case GPUBindingType::SampledTexture: {
226224 auto textureResource = tryGetResourceAsTexture(resourceBinding.resource, functionName);
227225 if (!textureResource)
228  return false;
 226 return nullptr;
229227 if (isForVertex)
230228 setTextureOnEncoder(vertexEncoder, textureResource->platformTexture(), index);
231229 if (isForFragment)

@@RefPtr<GPUBindGroup> GPUBindGroup::tryCreate(const GPUBindGroupDescriptor& descr
233231 if (isForCompute)
234232 setTextureOnEncoder(computeEncoder, textureResource->platformTexture(), index);
235233 boundTextures.append(textureResource.releaseNonNull());
236  return true;
237  }, [&](GPUBindGroupLayout::StorageBuffer& storageBuffer) -> bool {
238  return handleBuffer(storageBuffer.internalLengthName);
239  }, [&](GPUBindGroupLayout::DynamicStorageBuffer& dynamicStorageBuffer) -> bool {
240  return handleBuffer(dynamicStorageBuffer.internalLengthName);
241  }), layoutBinding.internalBindingDetails);
242  if (!success)
 234 break;
 235 }
 236 default:
 237 LOG(WebGPU, "%s: Resource type not yet implemented.", functionName);
243238 return nullptr;
 239 }
244240 }
245241
246242 return adoptRef(new GPUBindGroup(WTFMove(vertexArgsBuffer), WTFMove(fragmentArgsBuffer), WTFMove(computeArgsBuffer), WTFMove(boundBuffers), WTFMove(boundTextures)));

Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm

@@static OptionSet<WHLSL::ShaderStage> convertShaderStageFlags(GPUShaderStageFlags
110110 return result;
111111}
112112
113 static Optional<WHLSL::Binding::BindingDetails> convertBindingType(GPUBindGroupLayout::InternalBindingDetails internalBindingDetails)
 113static Optional<WHLSL::BindingType> convertBindingType(GPUBindingType type)
114114{
115  return WTF::visit(WTF::makeVisitor([&](GPUBindGroupLayout::UniformBuffer uniformBuffer) -> Optional<WHLSL::Binding::BindingDetails> {
116  return { WHLSL::UniformBufferBinding { uniformBuffer.internalLengthName } };
117  }, [&](GPUBindGroupLayout::DynamicUniformBuffer) -> Optional<WHLSL::Binding::BindingDetails> {
118  return WTF::nullopt;
119  }, [&](GPUBindGroupLayout::Sampler) -> Optional<WHLSL::Binding::BindingDetails> {
120  return { WHLSL::SamplerBinding { } };
121  }, [&](GPUBindGroupLayout::SampledTexture) -> Optional<WHLSL::Binding::BindingDetails> {
122  return { WHLSL::TextureBinding { } };
123  }, [&](GPUBindGroupLayout::StorageBuffer storageBuffer) -> Optional<WHLSL::Binding::BindingDetails> {
124  return { WHLSL::StorageBufferBinding { storageBuffer.internalLengthName } };
125  }, [&](GPUBindGroupLayout::DynamicStorageBuffer) -> Optional<WHLSL::Binding::BindingDetails> {
 115 switch (type) {
 116 case GPUBindingType::UniformBuffer:
 117 return WHLSL::BindingType::UniformBuffer;
 118 case GPUBindingType::Sampler:
 119 return WHLSL::BindingType::Sampler;
 120 case GPUBindingType::SampledTexture:
 121 return WHLSL::BindingType::Texture;
 122 case GPUBindingType::StorageBuffer:
 123 return WHLSL::BindingType::StorageBuffer;
 124 default:
126125 return WTF::nullopt;
127  }), internalBindingDetails);
 126 }
128127}
129128
130129static Optional<WHLSL::TextureFormat> convertTextureFormat(GPUTextureFormat format)

@@static Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout& layout)
378377 WHLSL::BindGroup bindGroup;
379378 bindGroup.name = static_cast<unsigned>(i);
380379 for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) {
381  const auto& bindingDetails = keyValuePair.value;
 380 const auto& gpuBindGroupLayoutBinding = keyValuePair.value;
382381 WHLSL::Binding binding;
383  binding.visibility = convertShaderStageFlags(bindingDetails.externalBinding.visibility);
384  if (auto bindingType = convertBindingType(bindingDetails.internalBindingDetails))
385  binding.binding = *bindingType;
 382 binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility);
 383 if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type))
 384 binding.bindingType = *bindingType;
386385 else
387386 return WTF::nullopt;
388  if (bindingDetails.externalBinding.binding > std::numeric_limits<unsigned>::max())
 387 if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max())
389388 return WTF::nullopt;
390  binding.externalName = bindingDetails.externalBinding.binding;
391  binding.internalName = bindingDetails.internalName;
 389 binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding);
392390 bindGroup.bindings.append(WTFMove(binding));
393391 }
394392 result.append(WTFMove(bindGroup));