⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 246394 in webkit


Ignore:
Timestamp:
Jun 12, 2019, 10:38:28 PM (7 years ago)
Author:
mmaxfield@apple.com
Message:

[WHLSL] Implement array references
https://bugs.webkit.org/show_bug.cgi?id=198163

Reviewed by Saam Barati.

Source/WebCore:

The compiler automatically generates anders for every array reference. Luckily, the infrastructure
to generate those anders and emit Metal code to represent them already exists in the compiler.
There are two pieces remaining (which this patch implements):

  1. The JavaScript compiler has a behavior where anders that are called with an array reference as an argument don't wrap the argument in a MakePointerExpression. This is because the array reference is already a reference type, so it's silly to operate on a pointer to a reference. This patch implements this by teaching the type checker about which types should be passed to the ander call, and by actually constructing those types in the property resolver. The property resolver does this by placing the logic to construct an ander argument in a single function which also has logic to save the argument in a temporary if the thread ander will be called. The semantics about which functions are called in which situations are not changed; instead, we just simply don't wrap array references with MakePointerExpressions.
  1. Creating a bind group from the WebGPU API has to retain information about buffer lengths for each buffer so the shader can properly perform bounds checks. This can be broken down into a few pieces:
    • Creating a bind group layout has to assign extra id indexes for each buffer which will be filled in to represent the buffer's length
    • Creating the bind group itself needs to fill in the buffer length into the Metal argument buffer
    • The shader compiler needs to emit code at the beginning of entry point to find the buffer lengths and pack them together into the array reference (array references correspond to a Metal struct with two fields: a pointer and a length).

This patch doesn't actually implement bounds checks themselves; it just hooks up the buffer
lengths so https://bugs.webkit.org/show_bug.cgi?id=198600 can implement it.

The shader compiler's API is modified to allow for this extra buffer length information to be
passed in from the WebGPU implementation.

Unfortunately, I don't think I could split this patch up into two pieces because both are
required to test the compiler with buffers.

Tests: webgpu/whlsl-buffer-fragment.html

webgpu/whlsl-buffer-vertex.html

  • Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h:

(WebCore::WHLSL::AST::PropertyAccessExpression::baseReference):

  • Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp:

(WebCore::WHLSL::AST::ResourceSemantic::isAcceptableType const): Arrays can't be resources
because the compiler has no way of guaranteeing if the resource is long enough to hold the
array at compile time.

  • Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp:

(WebCore::WHLSL::Metal::EntryPointScaffolding::EntryPointScaffolding): Generate an extra
variable name to represent the buffer length. Only do it for resources which have lengths.
(WebCore::WHLSL::Metal::EntryPointScaffolding::resourceHelperTypes):
(WebCore::WHLSL::Metal::EntryPointScaffolding::unpackResourcesAndNamedBuiltIns): Perform
the appropriate math to turn byte lengths into element counts and store the element count
in the array reference.

  • Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h:
  • Modules/webgpu/WHLSL/WHLSLChecker.cpp:

(WebCore::WHLSL::resolveWithOperatorAnderIndexer): Refactor.
(WebCore::WHLSL::resolveWithOperatorLength): Ditto.
(WebCore::WHLSL::resolveWithReferenceComparator): Ditto.
(WebCore::WHLSL::resolveByInstantiation): Ditto.
(WebCore::WHLSL::argumentTypeForAndOverload): Given an ander, what should the type of the
argument be?
(WebCore::WHLSL::Checker::finishVisiting): Call argumentTypeForAndOverload(). Also, if
we couldn't find an ander, try automatically generating it, the same way that function
calls do. (This is how array references get their anders.)
(WebCore::WHLSL::Checker::visit):

  • Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h: New WHLSL API to provide the length

information.

  • Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp:

(WebCore::WHLSL::PropertyResolver::visit): SimplifyRightValue() can't fail any more.
(WebCore::WHLSL::wrapAnderCallArgument): If the ander argument should be wrapped in a
MakePointer or a MakeArrayReference, do that. Also, if the ander is a thread ander, save
the argument in a local variable and use that.
(WebCore::WHLSL::anderCallArgument): The equivalent of argumentTypeForAndOverload().
(WebCore::WHLSL::setterCall): Call anderCallArgument().
(WebCore::WHLSL::getterCall): Ditto.
(WebCore::WHLSL::modify): We used to have special-case code for handling pointer-to-argument
values as distinct from just the argument values themselves. However, emitting
chains of &* operators is valid and won't even make it through the Metal code generator
after https://bugs.webkit.org/show_bug.cgi?id=198600 is fixed. So, in order to simplify
wrapAnderCallArgument(), don't special case these values and just create &* chains instead.
(WebCore::WHLSL::PropertyResolver::simplifyRightValue):
(WebCore::WHLSL::LeftValueSimplifier::finishVisiting): Call anderCallArgument().

  • Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp: Update to support the new compiler API.

(WebCore::WHLSL::matchMode):
(WebCore::WHLSL::matchResources):

  • Modules/webgpu/WebGPUBindGroupDescriptor.cpp: Ditto.

(WebCore::WebGPUBindGroupDescriptor::tryCreateGPUBindGroupDescriptor const):

  • platform/graphics/gpu/GPUBindGroupLayout.h: Add some internal implementation data inside

the bindings object. Use a Variant to differentiate between the various bindings types, and
put the extra length field on just those members of the variant that represent buffers.

  • platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm: Update to support the new compiler API.

(WebCore::argumentDescriptor):
(WebCore::GPUBindGroupLayout::tryCreate):

  • platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm: Ditto.

(WebCore::setBufferOnEncoder):
(WebCore::GPUBindGroup::tryCreate):

  • platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm: Ditto.

(WebCore::convertBindingType):
(WebCore::convertLayout):

LayoutTests:

  • webgpu/buffer-resource-triangles-expected.html: Deleted. This test doens't make any sense and triggers

Metal to read out-of-bounds of a vertex buffer.

  • webgpu/buffer-resource-triangles.html: Deleted.
  • webgpu/whlsl-buffer-fragment-expected.html: Added.
  • webgpu/whlsl-buffer-fragment.html: Added.
  • webgpu/whlsl-buffer-vertex-expected.html: Added.
  • webgpu/whlsl-buffer-vertex.html: Added.
  • webgpu/whlsl-dont-crash-parsing-enum.html:
  • webgpu/whlsl.html:
Location:
trunk
Files:
2 added
2 deleted
17 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r246393 r246394  
     12019-06-12  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [WHLSL] Implement array references
     4        https://bugs.webkit.org/show_bug.cgi?id=198163
     5
     6        Reviewed by Saam Barati.
     7
     8        * webgpu/buffer-resource-triangles-expected.html: Deleted. This test doens't make any sense and triggers
     9        Metal to read out-of-bounds of a vertex buffer.
     10        * webgpu/buffer-resource-triangles.html: Deleted.
     11        * webgpu/whlsl-buffer-fragment-expected.html: Added.
     12        * webgpu/whlsl-buffer-fragment.html: Added.
     13        * webgpu/whlsl-buffer-vertex-expected.html: Added.
     14        * webgpu/whlsl-buffer-vertex.html: Added.
     15        * webgpu/whlsl-dont-crash-parsing-enum.html:
     16        * webgpu/whlsl.html:
     17
    1182019-06-12  Justin Fan  <justin_fan@apple.com>
    219
  • trunk/LayoutTests/webgpu/whlsl-buffer-fragment.html

    r246393 r246394  
    1111}
    1212
    13 fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 {
    14     return position;
     13fragment float4 fragmentShader(float4 position : SV_Position, constant float[] theBuffer : register(b0)) : SV_Target 0 {
     14    return float4(theBuffer[0], theBuffer[0], theBuffer[0], 1.0);
    1515}
    1616`;
     
    7070    const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync();
    7171    const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer);
    72     vertexBuffer1Descriptor[0] = 1;
    73     vertexBuffer1Descriptor[1] = 1;
    74     vertexBuffer1Descriptor[2] = 1;
    75     vertexBuffer1Descriptor[3] = 1;
     72    vertexBuffer1Float32Array[0] = 1;
     73    vertexBuffer1Float32Array[1] = 1;
     74    vertexBuffer1Float32Array[2] = 1;
     75    vertexBuffer1Float32Array[3] = 1;
    7676    vertexBuffer1.unmap();
    7777
  • trunk/LayoutTests/webgpu/whlsl-buffer-vertex.html

    r246393 r246394  
    77<script>
    88const shaderSource = `
    9 vertex float4 vertexShader(float4 position : attribute(0), float i : attribute(1)) : SV_Position {
    10     return position;
     9vertex float4 vertexShader(constant float4[] buffer : register(b0), uint id : SV_VertexID) : SV_Position {
     10    return buffer[id];
    1111}
    1212
    1313fragment float4 fragmentShader(float4 position : SV_Position) : SV_Target 0 {
    14     return position;
     14    return float4(1.0, 1.0, 1.0, 1.0);
    1515}
    1616`;
     
    2828    const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL
    2929    const depthStencilState = null;
    30    
    31     const attribute0 = {shaderLocation: 0, format: "float4"};
    32     const attribute1 = {shaderLocation: 1, format: "float"};
    33     const input0 = {stride: 16, attributeSet: [attribute0]};
    34     const input1 = {stride: 4, attributeSet: [attribute1]};
    35     const inputs = [input0, input1];
    36     const vertexInput = {vertexBuffers: inputs};
     30
     31    const vertexInput = {vertexBuffers: []};
    3732
    3833    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    4439    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    4540
    46     const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE};
    47     const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor);
    48     const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync();
    49     const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer);
    50     vertexBuffer0Float32Array[0] = -0.5;
    51     vertexBuffer0Float32Array[1] = -0.5;
    52     vertexBuffer0Float32Array[2] = 1.0;
    53     vertexBuffer0Float32Array[3] = 1;
    54     vertexBuffer0Float32Array[4] = -0.5;
    55     vertexBuffer0Float32Array[5] = 0.5;
    56     vertexBuffer0Float32Array[6] = 1.0;
    57     vertexBuffer0Float32Array[7] = 1;
    58     vertexBuffer0Float32Array[8] = 0.5;
    59     vertexBuffer0Float32Array[9] = -0.5;
    60     vertexBuffer0Float32Array[10] = 1.0;
    61     vertexBuffer0Float32Array[11] = 1;
    62     vertexBuffer0Float32Array[12] = 0.5;
    63     vertexBuffer0Float32Array[13] = 0.5;
    64     vertexBuffer0Float32Array[14] = 1.0;
    65     vertexBuffer0Float32Array[15] = 1;
    66     vertexBuffer0.unmap();
    67 
    68     const vertexBuffer1Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE};
    69     const vertexBuffer1 = device.createBuffer(vertexBuffer1Descriptor);
    70     const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync();
    71     const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer);
    72     vertexBuffer1Descriptor[0] = 1;
    73     vertexBuffer1Descriptor[1] = 1;
    74     vertexBuffer1Descriptor[2] = 1;
    75     vertexBuffer1Descriptor[3] = 1;
    76     vertexBuffer1.unmap();
    77 
    78     const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};
     41    const resourceBufferDescriptor = {size: 4 * 4 * Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE};
    7942    const resourceBuffer = device.createBuffer(resourceBufferDescriptor);
    8043    const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync();
    8144    const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer);
    82     resourceBufferFloat32Array[0] = 1;
     45    resourceBufferFloat32Array[0] = -0.5;
     46    resourceBufferFloat32Array[1] = -0.5;
     47    resourceBufferFloat32Array[2] = 1.0;
     48    resourceBufferFloat32Array[3] = 1;
     49    resourceBufferFloat32Array[4] = -0.5;
     50    resourceBufferFloat32Array[5] = 0.5;
     51    resourceBufferFloat32Array[6] = 1.0;
     52    resourceBufferFloat32Array[7] = 1;
     53    resourceBufferFloat32Array[8] = 0.5;
     54    resourceBufferFloat32Array[9] = -0.5;
     55    resourceBufferFloat32Array[10] = 1.0;
     56    resourceBufferFloat32Array[11] = 1;
     57    resourceBufferFloat32Array[12] = 0.5;
     58    resourceBufferFloat32Array[13] = 0.5;
     59    resourceBufferFloat32Array[14] = 1.0;
     60    resourceBufferFloat32Array[15] = 1;
    8361    resourceBuffer.unmap();
    8462
     
    10381    renderPassEncoder.setPipeline(renderPipeline);
    10482    renderPassEncoder.setBindGroup(0, bindGroup);
    105     renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer1], [0, 0]);
    10683    renderPassEncoder.draw(4, 1, 0, 0);
    10784    renderPassEncoder.endPass();
  • trunk/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html

    r246390 r246394  
    7575    const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync();
    7676    const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer);
    77     vertexBuffer1Descriptor[0] = 1;
    78     vertexBuffer1Descriptor[1] = 1;
    79     vertexBuffer1Descriptor[2] = 1;
    80     vertexBuffer1Descriptor[3] = 1;
     77    vertexBuffer1Float32Array[0] = 1;
     78    vertexBuffer1Float32Array[1] = 1;
     79    vertexBuffer1Float32Array[2] = 1;
     80    vertexBuffer1Float32Array[3] = 1;
    8181    vertexBuffer1.unmap();
    8282
  • trunk/LayoutTests/webgpu/whlsl.html

    r246390 r246394  
    7070    const vertexBuffer1ArrayBuffer = await vertexBuffer1.mapWriteAsync();
    7171    const vertexBuffer1Float32Array = new Float32Array(vertexBuffer1ArrayBuffer);
    72     vertexBuffer1Descriptor[0] = 1;
    73     vertexBuffer1Descriptor[1] = 1;
    74     vertexBuffer1Descriptor[2] = 1;
    75     vertexBuffer1Descriptor[3] = 1;
     72    vertexBuffer1Float32Array[0] = 1;
     73    vertexBuffer1Float32Array[1] = 1;
     74    vertexBuffer1Float32Array[2] = 1;
     75    vertexBuffer1Float32Array[3] = 1;
    7676    vertexBuffer1.unmap();
    7777
  • trunk/Source/WebCore/ChangeLog

    r246391 r246394  
     12019-06-12  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [WHLSL] Implement array references
     4        https://bugs.webkit.org/show_bug.cgi?id=198163
     5
     6        Reviewed by Saam Barati.
     7
     8        The compiler automatically generates anders for every array reference. Luckily, the infrastructure
     9        to generate those anders and emit Metal code to represent them already exists in the compiler.
     10        There are two pieces remaining (which this patch implements):
     11
     12        1. The JavaScript compiler has a behavior where anders that are called with an array reference
     13           as an argument don't wrap the argument in a MakePointerExpression. This is because the array
     14           reference is already a reference type, so it's silly to operate on a pointer to a reference.
     15           This patch implements this by teaching the type checker about which types should be passed
     16           to the ander call, and by actually constructing those types in the property resolver.
     17           The property resolver does this by placing the logic to construct an ander argument in a
     18           single function which also has logic to save the argument in a temporary if the thread ander
     19           will be called. The semantics about which functions are called in which situations are not
     20           changed; instead, we just simply don't wrap array references with MakePointerExpressions.
     21
     22        2. Creating a bind group from the WebGPU API has to retain information about buffer lengths for
     23           each buffer so the shader can properly perform bounds checks. This can be broken down into a
     24           few pieces:
     25           - Creating a bind group layout has to assign extra id indexes for each buffer which will be
     26             filled in to represent the buffer's length
     27           - Creating the bind group itself needs to fill in the buffer length into the Metal argument
     28             buffer
     29           - The shader compiler needs to emit code at the beginning of entry point to find the buffer
     30             lengths and pack them together into the array reference (array references correspond to
     31             a Metal struct with two fields: a pointer and a length).
     32
     33        This patch doesn't actually implement bounds checks themselves; it just hooks up the buffer
     34        lengths so https://bugs.webkit.org/show_bug.cgi?id=198600 can implement it.
     35
     36        The shader compiler's API is modified to allow for this extra buffer length information to be
     37        passed in from the WebGPU implementation.
     38
     39        Unfortunately, I don't think I could split this patch up into two pieces because both are
     40        required to test the compiler with buffers.
     41
     42        Tests: webgpu/whlsl-buffer-fragment.html
     43               webgpu/whlsl-buffer-vertex.html
     44
     45        * Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h:
     46        (WebCore::WHLSL::AST::PropertyAccessExpression::baseReference):
     47        * Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp:
     48        (WebCore::WHLSL::AST::ResourceSemantic::isAcceptableType const): Arrays can't be resources
     49        because the compiler has no way of guaranteeing if the resource is long enough to hold the
     50        array at compile time.
     51        * Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp:
     52        (WebCore::WHLSL::Metal::EntryPointScaffolding::EntryPointScaffolding): Generate an extra
     53        variable name to represent the buffer length. Only do it for resources which have lengths.
     54        (WebCore::WHLSL::Metal::EntryPointScaffolding::resourceHelperTypes):
     55        (WebCore::WHLSL::Metal::EntryPointScaffolding::unpackResourcesAndNamedBuiltIns): Perform
     56        the appropriate math to turn byte lengths into element counts and store the element count
     57        in the array reference.
     58        * Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h:
     59        * Modules/webgpu/WHLSL/WHLSLChecker.cpp:
     60        (WebCore::WHLSL::resolveWithOperatorAnderIndexer): Refactor.
     61        (WebCore::WHLSL::resolveWithOperatorLength): Ditto.
     62        (WebCore::WHLSL::resolveWithReferenceComparator): Ditto.
     63        (WebCore::WHLSL::resolveByInstantiation): Ditto.
     64        (WebCore::WHLSL::argumentTypeForAndOverload): Given an ander, what should the type of the
     65        argument be?
     66        (WebCore::WHLSL::Checker::finishVisiting): Call argumentTypeForAndOverload(). Also, if
     67        we couldn't find an ander, try automatically generating it, the same way that function
     68        calls do. (This is how array references get their anders.)
     69        (WebCore::WHLSL::Checker::visit):
     70        * Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h: New WHLSL API to provide the length
     71        information.
     72        * Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp:
     73        (WebCore::WHLSL::PropertyResolver::visit): SimplifyRightValue() can't fail any more.
     74        (WebCore::WHLSL::wrapAnderCallArgument): If the ander argument should be wrapped in a
     75        MakePointer or a MakeArrayReference, do that. Also, if the ander is a thread ander, save
     76        the argument in a local variable and use that.
     77        (WebCore::WHLSL::anderCallArgument): The equivalent of argumentTypeForAndOverload().
     78        (WebCore::WHLSL::setterCall): Call anderCallArgument().
     79        (WebCore::WHLSL::getterCall): Ditto.
     80        (WebCore::WHLSL::modify): We used to have special-case code for handling pointer-to-argument
     81        values as distinct from just the argument values themselves. However, emitting
     82        chains of &* operators is valid and won't even make it through the Metal code generator
     83        after https://bugs.webkit.org/show_bug.cgi?id=198600 is fixed. So, in order to simplify
     84        wrapAnderCallArgument(), don't special case these values and just create &* chains instead.
     85        (WebCore::WHLSL::PropertyResolver::simplifyRightValue):
     86        (WebCore::WHLSL::LeftValueSimplifier::finishVisiting): Call anderCallArgument().
     87        * Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp: Update to support the new compiler API.
     88        (WebCore::WHLSL::matchMode):
     89        (WebCore::WHLSL::matchResources):
     90        * Modules/webgpu/WebGPUBindGroupDescriptor.cpp: Ditto.
     91        (WebCore::WebGPUBindGroupDescriptor::tryCreateGPUBindGroupDescriptor const):
     92        * platform/graphics/gpu/GPUBindGroupLayout.h: Add some internal implementation data inside
     93        the bindings object. Use a Variant to differentiate between the various bindings types, and
     94        put the extra length field on just those members of the variant that represent buffers.
     95        * platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm: Update to support the new compiler API.
     96        (WebCore::argumentDescriptor):
     97        (WebCore::GPUBindGroupLayout::tryCreate):
     98        * platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm: Ditto.
     99        (WebCore::setBufferOnEncoder):
     100        (WebCore::GPUBindGroup::tryCreate):
     101        * platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm: Ditto.
     102        (WebCore::convertBindingType):
     103        (WebCore::convertLayout):
     104
    11052019-06-12  Carlos Garcia Campos  <cgarcia@igalia.com>
    2106
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPropertyAccessExpression.h

    r245680 r246394  
    100100
    101101    Expression& base() { return m_base; }
     102    UniqueRef<Expression>& baseReference() { return m_base; }
    102103    UniqueRef<Expression> takeBase() { return WTFMove(m_base); }
    103104
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLResourceSemantic.cpp

    r245680 r246394  
    5050            return referenceType.addressSpace() == AddressSpace::Constant || referenceType.addressSpace() == AddressSpace::Device;
    5151        }
    52         if (is<ArrayType>(unnamedType))
    53             return true;
    5452        if (is<TypeReference>(unnamedType)) {
    5553            auto& typeReference = downcast<TypeReference>(unnamedType);
     
    7270        if (is<ReferenceType>(unnamedType))
    7371            return downcast<ReferenceType>(unnamedType).addressSpace() == AddressSpace::Constant;
    74         return is<ArrayType>(unnamedType);
     72        return false;
    7573    case Mode::Sampler:
    7674        return matches(unnamedType, intrinsics.samplerType());
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp

    r245759 r246394  
    3333#include "WHLSLGatherEntryPointItems.h"
    3434#include "WHLSLPipelineDescriptor.h"
     35#include "WHLSLReferenceType.h"
    3536#include "WHLSLResourceSemantic.h"
    3637#include "WHLSLStageInOutSemantic.h"
     
    109110            NamedBinding namedBinding;
    110111            namedBinding.elementName = m_typeNamer.generateNextStructureElementName();
    111             namedBinding.index = m_layout[i].bindings[j].name; // GPUBindGroupLayout::tryCreate() makes sure these don't collide.
     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);
    112122            namedBindGroup.namedBindings.uncheckedAppend(WTFMove(namedBinding));
    113123        }
     
    138148            if (iterator == m_resourceMap.end())
    139149                continue;
    140             auto mangledTypeName = m_typeNamer.mangledNameForType(*m_entryPointItems.inputs[iterator->value].unnamedType);
     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());
    141155            auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
    142156            auto index = m_namedBindGroups[i].namedBindings[j].index;
    143             stringBuilder.append(makeString("    ", mangledTypeName, ' ', elementName, " [[id(", index, ")]];\n"));
     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"));
    144160        }
    145161        stringBuilder.append("};\n\n");
     
    258274            if (iterator == m_resourceMap.end())
    259275                continue;
    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"));
     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            }
    263298        }
    264299    }
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.h

    r243091 r246394  
    7878    std::function<String()> m_generateNextVariableName;
    7979
     80    struct LengthInformation {
     81        String elementName;
     82        String temporaryName;
     83        unsigned index;
     84    };
    8085    struct NamedBinding {
    8186        String elementName;
    8287        unsigned index;
     88        Optional<LengthInformation> lengthInformation;
    8389    };
    8490    struct NamedBindGroup {
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp

    r246385 r246394  
    118118};
    119119
    120 static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(AST::CallExpression& callExpression, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics)
     120static AST::NativeFunctionDeclaration resolveWithOperatorAnderIndexer(Lexer::Token origin, AST::ArrayReferenceType& firstArgument, const Intrinsics& intrinsics)
    121121{
    122122    const bool isOperator = true;
    123     auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(callExpression.origin()), firstArgument.addressSpace(), firstArgument.elementType().clone());
     123    auto returnType = makeUniqueRef<AST::PointerType>(Lexer::Token(origin), firstArgument.addressSpace(), firstArgument.elementType().clone());
    124124    AST::VariableDeclarations parameters;
    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));
    128 }
    129 
    130 static AST::NativeFunctionDeclaration resolveWithOperatorLength(AST::CallExpression& callExpression, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics)
     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));
     128}
     129
     130static AST::NativeFunctionDeclaration resolveWithOperatorLength(Lexer::Token origin, AST::UnnamedType& firstArgument, const Intrinsics& intrinsics)
    131131{
    132132    const bool isOperator = true;
    133     auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.uintType());
     133    auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.uintType());
    134134    AST::VariableDeclarations parameters;
    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));
    137 }
    138 
    139 static AST::NativeFunctionDeclaration resolveWithReferenceComparator(AST::CallExpression& callExpression, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics)
     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));
     137}
     138
     139static AST::NativeFunctionDeclaration resolveWithReferenceComparator(Lexer::Token origin, ResolvingType& firstArgument, ResolvingType& secondArgument, const Intrinsics& intrinsics)
    140140{
    141141    const bool isOperator = true;
    142     auto returnType = AST::TypeReference::wrap(Lexer::Token(callExpression.origin()), intrinsics.boolType());
     142    auto returnType = AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.boolType());
    143143    auto argumentType = firstArgument.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> UniqueRef<AST::UnnamedType> {
    144144        return unnamedType->clone();
     
    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(callExpression.origin()), intrinsics.intType());
     152            return AST::TypeReference::wrap(Lexer::Token(origin), intrinsics.intType());
    153153        }));
    154154    }));
    155155    AST::VariableDeclarations parameters;
    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));
     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));
    159159}
    160160
     
    165165};
    166166
    167 static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(AST::CallExpression& callExpression, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics)
    168 {
    169     if (callExpression.name() == "operator&[]" && types.size() == 2) {
     167static Optional<AST::NativeFunctionDeclaration> resolveByInstantiation(const String& name, Lexer::Token origin, const Vector<std::reference_wrapper<ResolvingType>>& types, const Intrinsics& intrinsics)
     168{
     169    if (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)))
     
    181181        }));
    182182        if (firstArgumentArrayRef && secondArgumentIsUint)
    183             return resolveWithOperatorAnderIndexer(callExpression, *firstArgumentArrayRef, intrinsics);
    184     } else if (callExpression.name() == "operator.length" && types.size() == 1) {
     183            return resolveWithOperatorAnderIndexer(origin, *firstArgumentArrayRef, intrinsics);
     184    } else if (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)))
     
    191191        }));
    192192        if (firstArgumentReference)
    193             return resolveWithOperatorLength(callExpression, *firstArgumentReference, intrinsics);
    194     } else if (callExpression.name() == "operator==" && types.size() == 2) {
     193            return resolveWithOperatorLength(origin, *firstArgumentReference, intrinsics);
     194    } else if (name == "operator==" && types.size() == 2) {
    195195        auto acceptability = [](ResolvingType& resolvingType) -> Acceptability {
    196196            return resolvingType.visit(WTF::makeVisitor([](UniqueRef<AST::UnnamedType>& unnamedType) -> Acceptability {
     
    211211            success = true;
    212212        if (success)
    213             return resolveWithReferenceComparator(callExpression, types[0].get(), types[1].get(), intrinsics);
     213            return resolveWithReferenceComparator(origin, types[0].get(), types[1].get(), intrinsics);
    214214    }
    215215    return WTF::nullopt;
     
    970970}
    971971
     972static 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
    972995void Checker::finishVisiting(AST::PropertyAccessExpression& propertyAccessExpression, ResolvingType* additionalArgumentType)
    973996{
     
    9931016    auto leftAddressSpace = baseInfo->typeAnnotation.leftAddressSpace();
    9941017    if (leftAddressSpace) {
    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 = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes)))
    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
     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 = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), anderArgumentTypes)))
     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        }
    10011031    }
    10021032
    10031033    AST::FunctionDeclaration* threadAnderFunction = nullptr;
    10041034    AST::UnnamedType* threadAnderReturnType = nullptr;
    1005     {
     1035    if (auto argumentTypeForAndOverload = WHLSL::argumentTypeForAndOverload(*baseUnnamedType, AST::AddressSpace::Thread)) {
    10061036        ResolvingType argumentType = { makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, baseUnnamedType->get().clone()) };
    10071037        Vector<std::reference_wrapper<ResolvingType>> threadAnderArgumentTypes { argumentType };
     
    10101040        if ((threadAnderFunction = resolveFunctionOverload(propertyAccessExpression.possibleAnderOverloads(), threadAnderArgumentTypes)))
    10111041            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        }
    10121047    }
    10131048
     
    14351470    auto* function = resolveFunctionOverload(*callExpression.overloads(), types, callExpression.castReturnType());
    14361471    if (!function) {
    1437         if (auto newFunction = resolveByInstantiation(callExpression, types, m_intrinsics)) {
     1472        if (auto newFunction = resolveByInstantiation(callExpression.name(), callExpression.origin(), types, m_intrinsics)) {
    14381473            m_program.append(WTFMove(*newFunction));
    14391474            function = &m_program.nativeFunctionDeclarations().last();
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPipelineDescriptor.h

    r245759 r246394  
    115115};
    116116
    117 enum 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
     117struct UniformBufferBinding {
     118    unsigned lengthName;
    123119};
    124120
     121struct SamplerBinding {
     122};
     123
     124struct TextureBinding {
     125};
     126
     127struct StorageBufferBinding {
     128    unsigned lengthName;
     129};
     130
     131// FIXME: https://bugs.webkit.org/show_bug.cgi?id=198168 Add the dynamic types
     132
    125133struct Binding {
     134    using BindingDetails = Variant<UniformBufferBinding, SamplerBinding, TextureBinding, StorageBufferBinding>;
    126135    OptionSet<ShaderStage> visibility;
    127     BindingType bindingType;
    128     unsigned name;
     136    BindingDetails binding;
     137    unsigned internalName;
     138    unsigned externalName;
    129139};
    130140
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPropertyResolver.cpp

    r246385 r246394  
    3636#include "WHLSLFunctionDeclaration.h"
    3737#include "WHLSLFunctionDefinition.h"
     38#include "WHLSLMakeArrayReferenceExpression.h"
    3839#include "WHLSLMakePointerExpression.h"
    3940#include "WHLSLPointerType.h"
     
    5657    void visit(AST::ReadModifyWriteExpression&) override;
    5758
    58     bool simplifyRightValue(AST::PropertyAccessExpression&);
     59    void simplifyRightValue(AST::PropertyAccessExpression&);
    5960    bool simplifyAbstractLeftValue(AST::AssignmentExpression&, AST::DotExpression&, UniqueRef<AST::Expression>&& right);
    6061    void simplifyLeftValue(AST::Expression&);
     
    6667{
    6768    // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value.
    68     if (!simplifyRightValue(dotExpression))
    69         setError();
     69    simplifyRightValue(dotExpression);
    7070}
    7171
     
    7474    checkErrorAndVisit(indexExpression.indexExpression());
    7575    // Unless we're inside an AssignmentExpression or a ReadModifyWriteExpression, we're a right value.
    76     if (!simplifyRightValue(indexExpression))
    77         setError();
     76    simplifyRightValue(indexExpression);
    7877}
    7978
     
    8584}
    8685
    87 static 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)
     86enum class WhichAnder {
     87    ThreadAnder,
     88    Ander
     89};
     90
     91struct AnderCallArgumentResult {
     92    UniqueRef<AST::Expression> expression;
     93    Optional<UniqueRef<AST::VariableDeclaration>> variableDeclaration;
     94    WhichAnder whichAnder;
     95};
     96
     97template <typename ExpressionConstructor, typename TypeConstructor>
     98static 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::Ander }};
     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
     143static 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::Ander }};
     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
     157static 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)
    88158{
    89159    auto maybeAddIndexArgument = [&](Vector<UniqueRef<AST::Expression>>& arguments) {
     
    99169    if (relevantAnder) {
    100170        // *operator&.foo(&v) = newValue
     171        auto leftValue = leftValueFactory();
     172        auto argument = anderCallArgument(leftValue, true, true);
     173        ASSERT(argument);
     174        ASSERT(!argument->variableDeclaration);
     175        ASSERT(argument->whichAnder == WhichAnder::Ander);
    101176        Vector<UniqueRef<AST::Expression>> arguments;
    102         arguments.append(pointerToLeftValueFactory());
     177        arguments.append(WTFMove(argument->expression));
    103178        maybeAddIndexArgument(arguments);
    104179
     
    139214}
    140215
    141 static 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)
     216static Optional<UniqueRef<AST::Expression>> getterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable)
    142217{
    143218    auto maybeAddIndexArgument = [&](Vector<UniqueRef<AST::Expression>>& arguments) {
     
    153228    if (relevantAnder) {
    154229        // *operator&.foo(&v)
     230        auto leftValue = leftValueFactory();
     231        auto argument = anderCallArgument(leftValue, true, true);
     232        ASSERT(argument);
     233        ASSERT(!argument->variableDeclaration);
     234        ASSERT(argument->whichAnder == WhichAnder::Ander);
    155235        Vector<UniqueRef<AST::Expression>> arguments;
    156         arguments.append(pointerToLeftValueFactory());
     236        arguments.append(WTFMove(argument->expression));
    157237        maybeAddIndexArgument(arguments);
    158238
     
    171251    // operator.foo(v)
    172252    ASSERT(propertyAccessExpression.getterFunction());
    173    
     253
    174254    Vector<UniqueRef<AST::Expression>> arguments;
    175255    arguments.append(leftValueFactory());
     
    305385            return variableReference;
    306386        }
    307    
     387
    308388        auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
    309389        ASSERT(pointerVariable->type());
     
    317397        return dereferenceExpression;
    318398    };
    319     auto pointerToPreviousLeftValue = [&]() -> UniqueRef<AST::Expression> {
    320         if (previous) {
    321             auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(*previous));
    322             ASSERT(previous->type());
    323             variableReference->setType(previous->type()->clone());
    324             variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
    325 
    326             auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference));
    327             ASSERT(previous->type());
    328             makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, previous->type()->clone()));
    329             makePointerExpression->setTypeAnnotation(AST::RightValue());
    330             return makePointerExpression;
    331         }
    332 
    333         auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
    334         ASSERT(pointerVariable->type());
    335         variableReference->setType(pointerVariable->type()->clone());
    336         variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
    337         return variableReference;
    338     };
    339399    auto appendIndexAssignment = [&](AST::PropertyAccessExpression& propertyAccessExpression, Optional<UniqueRef<AST::VariableDeclaration>>& indexVariable) {
    340400        if (!indexVariable)
     
    362422
    363423        AST::FunctionDeclaration* relevantAnder = i == chain.size() - 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction();
    364         auto callExpression = getterCall(propertyAccessExpression, relevantAnder, previousLeftValue, pointerToPreviousLeftValue, indexVariable ? &*indexVariable : nullptr);
     424        auto callExpression = getterCall(propertyAccessExpression, relevantAnder, previousLeftValue, indexVariable ? &*indexVariable : nullptr);
    365425
    366426        if (!callExpression)
     
    377437
    378438        expressions.append(WTFMove(assignmentExpression));
    379        
     439
    380440        previous = &variableDeclaration;
    381441    }
    382442    appendIndexAssignment(chain[0], indexVariables[0]);
    383443    AST::FunctionDeclaration* relevantAnder = chain.size() == 1 ? propertyAccessExpression.anderFunction() : propertyAccessExpression.threadAnderFunction();
    384     auto lastGetterCallExpression = getterCall(chain[0], relevantAnder, previousLeftValue, pointerToPreviousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr);
     444    auto lastGetterCallExpression = getterCall(chain[0], relevantAnder, previousLeftValue, indexVariables[0] ? &*(indexVariables[0]) : nullptr);
    385445
    386446    // Step 3:
     
    405465            variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
    406466            return variableReference;
    407         }, [&]() -> UniqueRef<AST::Expression> {
    408             auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
    409             ASSERT(variableDeclaration.type());
    410             variableReference->setType(variableDeclaration.type()->clone());
    411             variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
    412 
    413             auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(propertyAccessExpression.origin()), WTFMove(variableReference));
    414             ASSERT(variableDeclaration.type());
    415             makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(propertyAccessExpression.origin()), AST::AddressSpace::Thread, variableDeclaration.type()->clone()));
    416             makePointerExpression->setTypeAnnotation(AST::RightValue());
    417             return makePointerExpression;
    418467        }, indexVariable ? &*indexVariable : nullptr);
    419468
     
    443492            dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(*pointerVariable->type()).addressSpace() });
    444493            return dereferenceExpression;
    445         }, [&]() -> UniqueRef<AST::Expression> {
    446             auto variableReference = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(pointerVariable));
    447             ASSERT(pointerVariable->type());
    448             variableReference->setType(pointerVariable->type()->clone());
    449             variableReference->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread }); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198169 Is this right?
    450             return variableReference;
    451494        }, indexVariables[indexVariables.size() - 1] ? &*(indexVariables[indexVariables.size() - 1]) : nullptr);
    452495
     
    672715}
    673716
    674 bool PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression)
     717static Optional<AnderCallArgumentResult> anderCallArgument(AST::PropertyAccessExpression& propertyAccessExpression)
     718{
     719    return anderCallArgument(propertyAccessExpression.baseReference(), propertyAccessExpression.anderFunction(), propertyAccessExpression.threadAnderFunction());
     720}
     721
     722void PropertyResolver::simplifyRightValue(AST::PropertyAccessExpression& propertyAccessExpression)
    675723{
    676724    Lexer::Token origin = propertyAccessExpression.origin();
     
    678726    checkErrorAndVisit(propertyAccessExpression.base());
    679727
    680     auto& base = propertyAccessExpression.base();
    681     if (auto leftAddressSpace = base.typeAnnotation().leftAddressSpace()) {
    682         if (auto* anderFunction = propertyAccessExpression.anderFunction()) {
    683             auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.takeBase());
    684             makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), *leftAddressSpace, base.resolvedType().clone()));
    685             makePointerExpression->setTypeAnnotation(AST::RightValue());
    686 
    687             Vector<UniqueRef<AST::Expression>> arguments;
    688             arguments.append(WTFMove(makePointerExpression));
    689             if (is<AST::IndexExpression>(propertyAccessExpression))
    690                 arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
    691             auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments));
    692             callExpression->setType(anderFunction->type().clone());
    693             callExpression->setTypeAnnotation(AST::RightValue());
    694             callExpression->setFunction(*anderFunction);
    695 
    696             auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression));
    697             dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone());
    698             dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() });
    699             return true;
    700         }
    701     }
    702 
    703     if (propertyAccessExpression.getterFunction()) {
    704         auto& getterFunction = *propertyAccessExpression.getterFunction();
     728    if (auto argument = anderCallArgument(propertyAccessExpression)) {
     729        auto* anderFunction = argument->whichAnder == WhichAnder::ThreadAnder ? propertyAccessExpression.threadAnderFunction() : propertyAccessExpression.anderFunction();
     730        ASSERT(anderFunction);
     731        auto origin = propertyAccessExpression.origin();
    705732        Vector<UniqueRef<AST::Expression>> arguments;
    706         arguments.append(propertyAccessExpression.takeBase());
     733        arguments.append(WTFMove(argument->expression));
    707734        if (is<AST::IndexExpression>(propertyAccessExpression))
    708735            arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
    709         auto* callExpression = AST::replaceWith<AST::CallExpression>(propertyAccessExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments));
    710         callExpression->setFunction(getterFunction);
    711         callExpression->setType(getterFunction.type().clone());
     736        auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(anderFunction->name()), WTFMove(arguments));
     737        callExpression->setType(anderFunction->type().clone());
    712738        callExpression->setTypeAnnotation(AST::RightValue());
    713         return true;
    714     }
    715 
    716     // 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.
    717     // This is effectively inlining the functions the spec says are generated.
    718     ASSERT(propertyAccessExpression.threadAnderFunction());
    719     auto* threadAnderFunction = propertyAccessExpression.threadAnderFunction();
    720 
    721     auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), base.resolvedType().clone(), String(), WTF::nullopt, WTF::nullopt);
    722 
    723     auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
    724     variableReference1->setType(base.resolvedType().clone());
    725     variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
    726 
    727     auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), propertyAccessExpression.takeBase());
    728     assignmentExpression->setType(base.resolvedType().clone());
    729     assignmentExpression->setTypeAnnotation(AST::RightValue());
    730 
    731     auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
    732     variableReference2->setType(base.resolvedType().clone());
    733     variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
    734 
    735     auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), WTFMove(variableReference2));
    736     makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), AST::AddressSpace::Thread, base.resolvedType().clone()));
    737     makePointerExpression->setTypeAnnotation(AST::RightValue());
    738 
     739        callExpression->setFunction(*anderFunction);
     740
     741        auto* dereferenceExpression = AST::replaceWith<AST::DereferenceExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(callExpression));
     742        dereferenceExpression->setType(downcast<AST::PointerType>(anderFunction->type()).elementType().clone());
     743        dereferenceExpression->setTypeAnnotation(AST::LeftValue { downcast<AST::PointerType>(anderFunction->type()).addressSpace() });
     744
     745        if (auto& variableDeclaration = argument->variableDeclaration)
     746            m_variableDeclarations.append(WTFMove(*variableDeclaration));
     747
     748        return;
     749    }
     750
     751    ASSERT(propertyAccessExpression.getterFunction());
     752    auto& getterFunction = *propertyAccessExpression.getterFunction();
    739753    Vector<UniqueRef<AST::Expression>> arguments;
    740     arguments.append(WTFMove(makePointerExpression));
     754    arguments.append(propertyAccessExpression.takeBase());
    741755    if (is<AST::IndexExpression>(propertyAccessExpression))
    742756        arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
    743     auto callExpression = makeUniqueRef<AST::CallExpression>(Lexer::Token(origin), String(threadAnderFunction->name()), WTFMove(arguments));
    744     callExpression->setType(threadAnderFunction->type().clone());
     757    auto* callExpression = AST::replaceWith<AST::CallExpression>(propertyAccessExpression, WTFMove(origin), String(getterFunction.name()), WTFMove(arguments));
     758    callExpression->setFunction(getterFunction);
     759    callExpression->setType(getterFunction.type().clone());
    745760    callExpression->setTypeAnnotation(AST::RightValue());
    746     callExpression->setFunction(*threadAnderFunction);
    747 
    748     auto dereferenceExpression = makeUniqueRef<AST::DereferenceExpression>(WTFMove(origin), WTFMove(callExpression));
    749     dereferenceExpression->setType(downcast<AST::PointerType>(threadAnderFunction->type()).elementType().clone());
    750     dereferenceExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
    751 
    752     Vector<UniqueRef<AST::Expression>> expressions;
    753     expressions.append(WTFMove(assignmentExpression));
    754     expressions.append(WTFMove(dereferenceExpression));
    755     auto* commaExpression = AST::replaceWith<AST::CommaExpression>(propertyAccessExpression, WTFMove(origin), WTFMove(expressions));
    756     commaExpression->setType(downcast<AST::PointerType>(threadAnderFunction->type()).elementType().clone());
    757     commaExpression->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
    758 
    759     m_variableDeclarations.append(WTFMove(variableDeclaration));
    760     return true;
    761 
    762761}
    763762
     
    778777    Lexer::Token origin = propertyAccessExpression.origin();
    779778    auto* anderFunction = propertyAccessExpression.anderFunction();
    780     auto& base = propertyAccessExpression.base();
    781     auto leftAddressSpace = *propertyAccessExpression.base().typeAnnotation().leftAddressSpace();
    782     auto makePointerExpression = makeUniqueRef<AST::MakePointerExpression>(Lexer::Token(origin), propertyAccessExpression.takeBase());
    783     makePointerExpression->setType(makeUniqueRef<AST::PointerType>(Lexer::Token(origin), leftAddressSpace, base.resolvedType().clone()));
    784     makePointerExpression->setTypeAnnotation(AST::RightValue());
     779
     780    auto argument = anderCallArgument(propertyAccessExpression);
     781    ASSERT(argument);
     782    ASSERT(!argument->variableDeclaration);
     783    ASSERT(argument->whichAnder == WhichAnder::Ander);
    785784
    786785    Vector<UniqueRef<AST::Expression>> arguments;
    787     arguments.append(WTFMove(makePointerExpression));
     786    arguments.append(WTFMove(argument->expression));
    788787    if (is<AST::IndexExpression>(propertyAccessExpression))
    789788        arguments.append(downcast<AST::IndexExpression>(propertyAccessExpression).takeIndex());
  • trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLSemanticMatcher.cpp

    r245759 r246394  
    5656};
    5757
    58 static bool matchMode(BindingType bindingType, AST::ResourceSemantic::Mode mode)
    59 {
    60     switch (bindingType) {
    61     case BindingType::UniformBuffer:
     58static bool matchMode(Binding::BindingDetails bindingType, AST::ResourceSemantic::Mode mode)
     59{
     60    return WTF::visit(WTF::makeVisitor([&](UniformBufferBinding) -> bool {
    6261        return mode == AST::ResourceSemantic::Mode::Buffer;
    63     case BindingType::Sampler:
     62    }, [&](SamplerBinding) -> bool {
    6463        return mode == AST::ResourceSemantic::Mode::Sampler;
    65     case BindingType::Texture:
     64    }, [&](TextureBinding) -> bool {
    6665        return mode == AST::ResourceSemantic::Mode::Texture;
    67     default:
    68         ASSERT(bindingType == BindingType::StorageBuffer);
     66    }, [&](StorageBufferBinding) -> bool {
    6967        return mode == AST::ResourceSemantic::Mode::UnorderedAccessView;
    70     }
     68    }), bindingType);
    7169}
    7270
     
    8886                    continue;
    8987                auto& resourceSemantic = WTF::get<AST::ResourceSemantic>(semantic);
    90                 if (!matchMode(binding.bindingType, resourceSemantic.mode()))
     88                if (!matchMode(binding.binding, resourceSemantic.mode()))
    9189                    continue;
    92                 if (binding.name != resourceSemantic.index())
     90                if (binding.externalName != resourceSemantic.index())
    9391                    continue;
    9492                if (space != resourceSemantic.space())
  • trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp

    r243636 r246394  
    112112                return WTF::nullopt;
    113113
    114             if (!validateBufferBindingType(buffer, layoutBinding, functionName))
     114            if (!validateBufferBindingType(buffer, layoutBinding.externalBinding, functionName))
    115115                return WTF::nullopt;
    116116
     
    120120        auto bindingResource = WTF::visit(bindingResourceVisitor, binding.resource);
    121121        if (!bindingResource) {
    122             LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.binding);
     122            LOG(WebGPU, "%s: Invalid resource for binding %u!", functionName, layoutBinding.externalBinding.binding);
    123123            return WTF::nullopt;
    124124        }
  • trunk/Source/WebCore/platform/graphics/gpu/GPUBindGroupLayout.h

    r243658 r246394  
    3434#include <wtf/RefPtr.h>
    3535#include <wtf/RetainPtr.h>
     36#include <wtf/Variant.h>
    3637
    3738#if USE(METAL)
     
    4849    static RefPtr<GPUBindGroupLayout> tryCreate(const GPUDevice&, const GPUBindGroupLayoutDescriptor&);
    4950
    50     using BindingsMapType = HashMap<uint64_t, GPUBindGroupLayoutBinding, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
     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>>;
    5182    const BindingsMapType& bindingsMap() const { return m_bindingsMap; }
    5283#if USE(METAL)
  • trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm

    r243636 r246394  
    7878};
    7979
     80static 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 setDataType:dataType];
     88    [mtlArgument setIndex:index];
     89    return mtlArgument;
     90}
     91
    8092RefPtr<GPUBindGroupLayout> GPUBindGroupLayout::tryCreate(const GPUDevice& device, const GPUBindGroupLayoutDescriptor& descriptor)
    8193{
     
    88100    BindingsMapType bindingsMap;
    89101
     102    unsigned internalName = 0;
     103    unsigned internalLengthBase = descriptor.bindings.size();
    90104    for (const auto& binding : descriptor.bindings) {
    91         if (!bindingsMap.add(binding.binding, binding)) {
     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)) {
    92129            LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Duplicate binding %u found in GPUBindGroupLayoutDescriptor!", binding.binding);
    93130            return nullptr;
    94131        }
    95132
    96         RetainPtr<MTLArgumentDescriptor> mtlArgument;
     133        RetainPtr<MTLArgumentDescriptor> mtlArgument = argumentDescriptor(MTLDataTypeForBindingType(binding.type), bindingDetails.internalName);
    97134
    98         BEGIN_BLOCK_OBJC_EXCEPTIONS;
    99         mtlArgument = adoptNS([MTLArgumentDescriptor new]);
    100         END_BLOCK_OBJC_EXCEPTIONS;
    101135        if (!mtlArgument) {
    102136            LOG(WebGPU, "GPUBindGroupLayout::tryCreate(): Unable to create MTLArgumentDescriptor for binding %u!", binding.binding);
     
    104138        }
    105139
    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);
     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;
    115158    }
    116159
    117160    RetainPtr<MTLArgumentEncoder> vertex, fragment, compute;
    118161
    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     }
     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;
    131168
    132169    return adoptRef(new GPUBindGroupLayout(WTFMove(bindingsMap), WTFMove(vertex), WTFMove(fragment), WTFMove(compute)));
  • trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm

    r244235 r246394  
    7373}
    7474
    75 static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned index)
     75static void setBufferOnEncoder(MTLArgumentEncoder *argumentEncoder, const GPUBufferBinding& bufferBinding, unsigned name, unsigned lengthName)
    7676{
    7777    ASSERT(argumentEncoder && bufferBinding.buffer->platformBuffer());
     
    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:index];
     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));
    8284    END_BLOCK_OBJC_EXCEPTIONS;
    8385}
     
    172174        }
    173175        auto layoutBinding = layoutIterator->value;
    174         if (layoutBinding.visibility == GPUShaderStageBit::Flags::None)
     176        if (layoutBinding.externalBinding.visibility == GPUShaderStageBit::Flags::None)
    175177            continue;
    176178
    177         bool isForVertex = layoutBinding.visibility & GPUShaderStageBit::Flags::Vertex;
    178         bool isForFragment = layoutBinding.visibility & GPUShaderStageBit::Flags::Fragment;
    179         bool isForCompute = layoutBinding.visibility & GPUShaderStageBit::Flags::Compute;
     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;
    180182
    181183        if (isForVertex && !vertexEncoder) {
     
    192194        }
    193195
    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: {
     196        auto handleBuffer = [&](unsigned internalLengthName) -> bool {
    199197            auto bufferResource = tryGetResourceAsBufferBinding(resourceBinding.resource, functionName);
    200198            if (!bufferResource)
    201                 return nullptr;
     199                return false;
    202200            if (isForVertex)
    203                 setBufferOnEncoder(vertexEncoder, *bufferResource, index);
     201                setBufferOnEncoder(vertexEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
    204202            if (isForFragment)
    205                 setBufferOnEncoder(fragmentEncoder, *bufferResource, index);
     203                setBufferOnEncoder(fragmentEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
    206204            if (isForCompute)
    207                 setBufferOnEncoder(computeEncoder, *bufferResource, index);
     205                setBufferOnEncoder(computeEncoder, *bufferResource, layoutBinding.internalName, internalLengthName);
    208206            boundBuffers.append(bufferResource->buffer.copyRef());
    209             break;
    210         }
    211         case GPUBindingType::Sampler: {
     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 {
    212215            auto samplerState = tryGetResourceAsMtlSampler(resourceBinding.resource, functionName);
    213216            if (!samplerState)
    214                 return nullptr;
     217                return false;
    215218            if (isForVertex)
    216219                setSamplerOnEncoder(vertexEncoder, samplerState, index);
     
    219222            if (isForCompute)
    220223                setSamplerOnEncoder(computeEncoder, samplerState, index);
    221             break;
    222         }
    223         case GPUBindingType::SampledTexture: {
     224            return true;
     225        }, [&](GPUBindGroupLayout::SampledTexture&) -> bool {
    224226            auto textureResource = tryGetResourceAsTexture(resourceBinding.resource, functionName);
    225227            if (!textureResource)
    226                 return nullptr;
     228                return false;
    227229            if (isForVertex)
    228230                setTextureOnEncoder(vertexEncoder, textureResource->platformTexture(), index);
     
    232234                setTextureOnEncoder(computeEncoder, textureResource->platformTexture(), index);
    233235            boundTextures.append(textureResource.releaseNonNull());
    234             break;
    235         }
    236         default:
    237             LOG(WebGPU, "%s: Resource type not yet implemented.", functionName);
    238             return nullptr;
    239         }
     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)
     243            return nullptr;
    240244    }
    241245   
  • trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm

    r245905 r246394  
    111111}
    112112
    113 static Optional<WHLSL::BindingType> convertBindingType(GPUBindingType type)
    114 {
    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:
     113static Optional<WHLSL::Binding::BindingDetails> convertBindingType(GPUBindGroupLayout::InternalBindingDetails internalBindingDetails)
     114{
     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> {
    125118        return WTF::nullopt;
    126     }
     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> {
     126        return WTF::nullopt;
     127    }), internalBindingDetails);
    127128}
    128129
     
    378379        bindGroup.name = static_cast<unsigned>(i);
    379380        for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) {
    380             const auto& gpuBindGroupLayoutBinding = keyValuePair.value;
     381            const auto& bindingDetails = keyValuePair.value;
    381382            WHLSL::Binding binding;
    382             binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility);
    383             if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type))
    384                 binding.bindingType = *bindingType;
     383            binding.visibility = convertShaderStageFlags(bindingDetails.externalBinding.visibility);
     384            if (auto bindingType = convertBindingType(bindingDetails.internalBindingDetails))
     385                binding.binding = *bindingType;
    385386            else
    386387                return WTF::nullopt;
    387             if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max())
     388            if (bindingDetails.externalBinding.binding > std::numeric_limits<unsigned>::max())
    388389                return WTF::nullopt;
    389             binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding);
     390            binding.externalName = bindingDetails.externalBinding.binding;
     391            binding.internalName = bindingDetails.internalName;
    390392            bindGroup.bindings.append(WTFMove(binding));
    391393        }
Note: See TracChangeset for help on using the changeset viewer.