Changeset 245905 in webkit


Ignore:
Timestamp:
May 30, 2019 2:05:16 PM (5 years ago)
Author:
Justin Fan
Message:

[Web GPU] Vertex Buffers/Input State API updates
https://bugs.webkit.org/show_bug.cgi?id=194258
<rdar://problem/47806127>

Reviewed by Myles C. Maxfield.

Source/WebCore:

The vertex buffer attributes model for GPURenderPipelines in the WebGPU API has been updated.
Update our implementation to match.

No new tests. Existing tests updated to match new behavior.

  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • Modules/webgpu/GPUVertexAttributeDescriptor.idl:
  • Modules/webgpu/GPUVertexBufferDescriptor.idl: Renamed from Source/WebCore/Modules/webgpu/GPUInputStateDescriptor.idl.
  • Modules/webgpu/GPUVertexInputDescriptor.idl:
  • Modules/webgpu/WebGPURenderPipelineDescriptor.idl:
  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • platform/graphics/gpu/GPURenderPipelineDescriptor.h:
  • platform/graphics/gpu/GPUVertexAttributeDescriptor.h:
  • platform/graphics/gpu/GPUVertexBufferDescriptor.h: Renamed from Source/WebCore/platform/graphics/gpu/GPUInputStateDescriptor.h.
  • platform/graphics/gpu/GPUVertexInputDescriptor.h:
  • platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm:

(WebCore::trySetVertexInput): Added. Populate Metal and WHLSL pipeline descriptors with vertex attribute metadata.
(WebCore::trySetColorStates): Added. Populate Metal and WHLSL pipeline descriptors with color attachment metadata.
(WebCore::convertLayout): Moved.
(WebCore::trySetMetalFunctions): Moved.
(WebCore::trySetFunctions): Added. WHLSL compilation to Metal SL happens here, then MSL functions are set on pipeline descriptor.
(WebCore::convertRenderPipelineDescriptor): Repurposed. Convert a GPURenderPipelineDescriptor to Metal and WHLSL versions.
(WebCore::tryCreateMtlRenderPipelineState):
(WebCore::GPURenderPipeline::tryCreate):
(WebCore::trySetMetalFunctionsForPipelineDescriptor): Deleted.
(WebCore::trySetWHLSLFunctionsForPipelineDescriptor): Deleted.
(WebCore::trySetFunctionsForPipelineDescriptor): Deleted.
(WebCore::trySetInputStateForPipelineDescriptor): Deleted.
(WebCore::setColorStatesForColorAttachmentArray): Deleted.

LayoutTests:

Update WebGPU tests for the new vertex buffer attributes model.

  • webgpu/blend-triangle-strip.html:
  • webgpu/buffer-command-buffer-races.html:
  • webgpu/buffer-resource-triangles.html:
  • webgpu/depth-enabled-triangle-strip.html:
  • webgpu/draw-indexed-triangles.html:
  • webgpu/js/webgpu-functions.js:
  • webgpu/texture-triangle-strip.html:
  • webgpu/vertex-buffer-triangle-strip.html:
  • webgpu/whlsl-arbitrary-vertex-attribute-locations.html:
  • webgpu/whlsl-dereference-pointer-should-type-check.html:
  • webgpu/whlsl-dont-crash-parsing-enum.html:
  • webgpu/whlsl-dot-expressions.html:
  • webgpu/whlsl-nested-dot-expression-rvalue.html:
  • webgpu/whlsl.html:
Location:
trunk
Files:
29 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245902 r245905  
     12019-05-30  Justin Fan  <justin_fan@apple.com>
     2
     3        [Web GPU] Vertex Buffers/Input State API updates
     4        https://bugs.webkit.org/show_bug.cgi?id=194258
     5        <rdar://problem/47806127>
     6
     7        Reviewed by Myles C. Maxfield.
     8
     9        Update WebGPU tests for the new vertex buffer attributes model.
     10
     11        * webgpu/blend-triangle-strip.html:
     12        * webgpu/buffer-command-buffer-races.html:
     13        * webgpu/buffer-resource-triangles.html:
     14        * webgpu/depth-enabled-triangle-strip.html:
     15        * webgpu/draw-indexed-triangles.html:
     16        * webgpu/js/webgpu-functions.js:
     17        * webgpu/texture-triangle-strip.html:
     18        * webgpu/vertex-buffer-triangle-strip.html:
     19        * webgpu/whlsl-arbitrary-vertex-attribute-locations.html:
     20        * webgpu/whlsl-dereference-pointer-should-type-check.html:
     21        * webgpu/whlsl-dont-crash-parsing-enum.html:
     22        * webgpu/whlsl-dot-expressions.html:
     23        * webgpu/whlsl-nested-dot-expression-rvalue.html:
     24        * webgpu/whlsl.html:
     25
    1262019-05-30  Wenson Hsieh  <wenson_hsieh@apple.com>
    227
  • trunk/LayoutTests/webgpu/blend-triangle-strip.html

    r244507 r245905  
    5757    }];
    5858
    59     const inputStateDescriptor = {
     59    const vertexInputDescriptor = {
    6060        indexFormat: "uint32",
    61         attributes: [{
    62             shaderLocation: positionAttributeNum,
    63             inputSlot: 0,
    64             format: "float4"
    65         }],
    66         inputs: [{
    67             inputSlot: 0,
    68             stride: 4 * 4
     61        vertexBuffers: [{
     62            stride: 4 * 4,
     63            attributeSet: [{
     64                format: "float4",
     65                shaderLocation: positionAttributeNum
     66            }]
    6967        }]
    7068    };
    7169
    72     const pipeline = createBasicPipeline(shaderModule, device, colorStates, null, inputStateDescriptor);
     70    const pipeline = createBasicPipeline(shaderModule, device, colorStates, null, vertexInputDescriptor);
    7371
    7472    const vertexData = new Float32Array([
  • trunk/LayoutTests/webgpu/buffer-command-buffer-races.html

    r244442 r245905  
    4343`
    4444
    45 function createInputStateDescriptor() {
     45function createVertexInputDescriptor() {
    4646    return {
    4747        indexFormat: "uint32",
    48         attributes: [{
    49             shaderLocation: 0,
    50             inputSlot: 0,
    51             format: "float2"
     48        vertexBuffers: [{
     49            stride: 4 * 2,
     50            attributeSet: [{
     51                format: "float2",
     52                shaderLocation: 0
     53            }]
    5254        }, {
    53             shaderLocation: 1,
    54             inputSlot: 1,
    55             format: "float3"
    56         }],
    57         inputs: [{
    58             inputSlot: 0,
    59             stride: 4 * 2
    60         }, {
    61             inputSlot: 1,
    6255            stride: 4 * 3,
    63             stepMode: "instance"
     56            stepMode: "instance",
     57            attributeSet: [{
     58                format: "float3",
     59                shaderLocation: 1
     60            }]
    6461        }]
    6562    }
     
    8986    // FIXME: Replace with non-MSL shaders.
    9087    const shaderModule = device.createShaderModule({ code: shaderCode });
    91     const inputStateDescriptor = createInputStateDescriptor();
    92     const pipeline = createBasicPipeline(shaderModule, device, null, null, inputStateDescriptor);
     88    const vertexInputDescriptor = createVertexInputDescriptor();
     89    const pipeline = createBasicPipeline(shaderModule, device, null, null, vertexInputDescriptor);
    9390
    9491    const upperLeftBuffer = createAndSetVertexBuffer(device, [-1, 1, -1, -1, 0, 1]);
  • trunk/LayoutTests/webgpu/buffer-resource-triangles.html

    r244856 r245905  
    133133
    134134    // Create vertex input state.
    135     const inputState = {
     135    const vertexInput = {
    136136        indexFormat: "uint32",
    137         attributes: [{
    138             shaderLocation: 0,
    139             inputSlot: 0,
    140             format: "float4"
    141         }],
    142         inputs: [{
    143             inputSlot: 0,
    144             stride: vertexSize
     137        vertexBuffers: [{
     138            stride: vertexSize,
     139            attributeSet: [{
     140                format: "float4",
     141                shaderLocation: 0
     142            }]
    145143        }]
    146144    };
     
    160158    // GPUPipelineLayout and GPURenderPipeline
    161159    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [leftTriangleBGLayout, rightTriangleBGLayout] });
    162     const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, inputState, null, "triangle-list");
     160    const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, vertexInput, null, "triangle-list");
    163161
    164162    // GPUBufferBindings
  • trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html

    r244442 r245905  
    6363}
    6464
    65 function createInputStateDescriptor() {
     65function createVertexInputDescriptor() {
    6666    return {
    6767        indexFormat: "uint32",
    68         attributes: [{
    69             shaderLocation: 0,
    70             inputSlot: 0,
    71             format: "float4"
    72         }],
    73         inputs: [{
    74             inputSlot: 0,
    75             stride: 4 * 4
     68        vertexBuffers: [{
     69            stride: 4 * 4,
     70            attributeSet: [{
     71                format: "float4",
     72                shaderLocation: 0
     73            }]
    7674        }]
    7775    }
     
    8583    const shaderModule = device.createShaderModule({ code: shaderCode });
    8684    const vertexBuffer = createVertexBuffer(device);
    87     const inputStateDescriptor = createInputStateDescriptor();
     85    const vertexInputDescriptor = createVertexInputDescriptor();
    8886    const depthStateDescriptor = createBasicDepthStateDescriptor();
    89     const pipeline = createBasicPipeline(shaderModule, device, null, null, inputStateDescriptor, depthStateDescriptor);
     87    const pipeline = createBasicPipeline(shaderModule, device, null, null, vertexInputDescriptor, depthStateDescriptor);
    9088    const commandEncoder = device.createCommandEncoder();
    9189
  • trunk/LayoutTests/webgpu/draw-indexed-triangles.html

    r244442 r245905  
    7272}
    7373
    74 function createInputStateDescriptor() {
     74function createVertexInputDescriptor() {
    7575    return {
    7676        indexFormat: "uint32",
    77         attributes: [{
    78             shaderLocation: 0,
    79             inputSlot: 0,
    80             format: "float4"
    81         }, {
    82             shaderLocation: 1,
    83             inputSlot: 0,
    84             offset: 4 * 4,
    85             format: "float"
    86         }],
    87         inputs: [{
    88             inputSlot: 0,
    89             stride: 4 * 5
     77        vertexBuffers: [{
     78            stride: 4 * 5,
     79            attributeSet: [{
     80                format: "float4",
     81                shaderLocation: 0
     82            }, {
     83                offset: 4 * 4,
     84                format: "float",
     85                shaderLocation: 1
     86            }]
    9087        }]
    9188    };
     
    10097    const vertexBuffer = createVertexBuffer(device);
    10198    const indexBuffer = createIndexBuffer(device);
    102     const pipeline = createBasicPipeline(shaderModule, device, null, null, createInputStateDescriptor(), null, "triangle-list");
     99    const pipeline = createBasicPipeline(shaderModule, device, null, null, createVertexInputDescriptor(), null, "triangle-list");
    103100    const commandEncoder = device.createCommandEncoder();
    104101    const passEncoder = beginBasicRenderPass(swapChain, commandEncoder);
  • trunk/LayoutTests/webgpu/js/webgpu-functions.js

    r244856 r245905  
    3131}
    3232
    33 function createBasicPipeline(shaderModule, device, colorStates, pipelineLayout, inputStateDescriptor, depthStateDescriptor, primitiveTopology = "triangle-strip") {
     33function createBasicPipeline(shaderModule, device, colorStates, pipelineLayout, vertexInputDescriptor, depthStateDescriptor, primitiveTopology = "triangle-strip") {
    3434    const vertexStageDescriptor = {
    3535        module: shaderModule,
     
    5050    }
    5151
    52     if (!inputStateDescriptor)
    53         inputStateDescriptor = { attributes: [], inputs: [] };
     52    if (!vertexInputDescriptor)
     53        vertexInputDescriptor = { vertexBuffers: [] };
    5454
    5555    const pipelineDescriptor = {
     
    5858        primitiveTopology: primitiveTopology,
    5959        colorStates: colorStates,
    60         inputState: inputStateDescriptor
     60        vertexInput: vertexInputDescriptor
    6161    };
    6262
  • trunk/LayoutTests/webgpu/texture-triangle-strip.html

    r244442 r245905  
    5656`
    5757
    58 function createInputStateDescriptor() {
    59     return {
    60         indexFormat: "uint32",
    61         attributes: [{
    62             shaderLocation: positionAttributeNum,
    63             inputSlot: positionBufferIndex,
    64             format: "float4"
    65         }, {
    66             shaderLocation: texCoordsAttributeNum,
    67             inputSlot: texCoordsBufferIndex,
    68             format: "float2"
    69         }],
    70         inputs: [{
    71             inputSlot: positionBufferIndex,
    72             stride: 4 * 4
    73         }, {
    74             inputSlot: texCoordsBufferIndex,
    75             stride: 4 * 2
     58function createVertexInputDescriptor() {
     59    var bufferDescriptors = [];
     60    bufferDescriptors[positionBufferIndex] = {
     61        stride: 4 * 4,
     62        attributeSet: [{
     63            format: "float4",
     64            shaderLocation: positionAttributeNum
    7665        }]
    77     }
     66    };
     67    bufferDescriptors[texCoordsBufferIndex] = {
     68        stride: 4 * 2,
     69        attributeSet: [{
     70            format: "float2",
     71            shaderLocation: texCoordsAttributeNum
     72        }]
     73    };
     74
     75    return { vertexBuffers: bufferDescriptors };
    7876}
    7977
     
    105103    textureCoordBuffer.setSubData(0, texCoordsArray.buffer);
    106104
    107     const inputStateDescriptor = createInputStateDescriptor();
     105    const vertexInputDescriptor = createVertexInputDescriptor();
    108106
    109107    // Load texture image
     
    178176
    179177    // Pipeline and render
    180     const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, inputStateDescriptor);
     178    const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, vertexInputDescriptor);
    181179    const commandEncoder = device.createCommandEncoder();
    182180
  • trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html

    r244442 r245905  
    6161}
    6262
    63 function createInputStateDescriptor() {
     63function createVertexInputDescriptor() {
    6464    return {
    65         indexFormat: "uint32",
    66         attributes: [{
    67             shaderLocation: 0,
    68             inputSlot: 0,
    69             format: "float4"
    70         }, {
    71             shaderLocation: 1,
    72             inputSlot: 0,
    73             offset: 4 * 4,
    74             format: "float"
    75         }],
    76         inputs: [{
    77             inputSlot: 0,
    78             stride: 4 * 5
     65        vertexBuffers: [{
     66            stride: 4 * 5,
     67            attributeSet: [{
     68                format: "float4",
     69                shaderLocation: 0
     70            }, {
     71                offset: 4 * 4,
     72                format: "float",
     73                shaderLocation: 1
     74            }]
    7975        }]
    8076    }
     
    8884    const shaderModule = device.createShaderModule({ code: shaderCode });
    8985    const vertexBuffer = createVertexBuffer(device);
    90     const inputStateDescriptor = createInputStateDescriptor();
    91     const pipeline = createBasicPipeline(shaderModule, device, null, null, inputStateDescriptor);
     86    const vertexInputDescriptor = createVertexInputDescriptor();
     87    const pipeline = createBasicPipeline(shaderModule, device, null, null, vertexInputDescriptor);
    9288    const commandEncoder = device.createCommandEncoder();
    9389    const passEncoder = beginBasicRenderPass(swapChain, commandEncoder);
  • trunk/LayoutTests/webgpu/whlsl-arbitrary-vertex-attribute-locations.html

    r245759 r245905  
    3737    const depthStencilState = null;
    3838
    39     const attribute0 = {shaderLocation: 173, inputSlot: 0, format: "float4", offset: 0};
    40     const attribute1 = {shaderLocation: 498, inputSlot: 0, format: "float", offset: 16};
    41     const attributes = [attribute0, attribute1];
    42     const input0 = {inputSlot: 0, stride: 20 };
     39    const attribute0 = {shaderLocation: 173, format: "float4"};
     40    const attribute1 = {shaderLocation: 498, format: "float", offset: 16};
     41    const input0 = {stride: 20, attributeSet: [attribute0, attribute1]};
    4342    const inputs = [input0];
    44     const inputState = {indexFormat: "uint32", attributes, inputs};
     43    const vertexInput = {vertexBuffers: inputs};
    4544
    4645    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    4948    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    5049
    51     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     50    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    5251    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    5352
  • trunk/LayoutTests/webgpu/whlsl-dereference-pointer-should-type-check.html

    r245844 r245905  
    4242    const depthStencilState = null;
    4343
    44     const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4", offset: 0};
    45     const attribute1 = {shaderLocation: 1, inputSlot: 0, format: "float", offset: 16};
     44    const attribute0 = {shaderLocation: 0, format: "float4", offset: 0};
     45    const attribute1 = {shaderLocation: 1, format: "float", offset: 16};
    4646    const attributes = [attribute0, attribute1];
    47     const input0 = {inputSlot: 0, stride: 20 };
     47    const input0 = {stride: 20, attributeSet: attributes};
    4848    const inputs = [input0];
    49     const inputState = {indexFormat: "uint32", attributes, inputs};
     49    const vertexInput = {vertexBuffers: inputs};
    5050
    5151    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    5454    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    5555
    56     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     56    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    5757    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    5858
  • trunk/LayoutTests/webgpu/whlsl-dont-crash-parsing-enum.html

    r245662 r245905  
    3434    const depthStencilState = null;
    3535   
    36     const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4"};
    37     const attribute1 = {shaderLocation: 1, inputSlot: 1, format: "float"};
    38     const attributes = [attribute0, attribute1];
    39     const input0 = {inputSlot: 0, stride: 16 };
    40     const input1 = {inputSlot: 1, stride: 4 };
     36    const attribute0 = {shaderLocation: 0, format: "float4"};
     37    const attribute1 = {shaderLocation: 1, format: "float"};
     38    const input0 = {stride: 16, attributeSet: [attribute0]};
     39    const input1 = {stride: 4, attributeSet: [attribute1]};
    4140    const inputs = [input0, input1];
    42     const inputState = {indexFormat: "uint32", attributes, inputs};
     41    const vertexInput = {vertexBuffers: inputs};
    4342
    4443    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    4746    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    4847
    49     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     48    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    5049    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    5150
  • trunk/LayoutTests/webgpu/whlsl-dot-expressions.html

    r245680 r245905  
    3737    const depthStencilState = null;
    3838
    39     const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4", offset: 0};
    40     const attribute1 = {shaderLocation: 1, inputSlot: 0, format: "float", offset: 16};
     39    const attribute0 = {shaderLocation: 0, format: "float4"};
     40    const attribute1 = {shaderLocation: 1, format: "float", offset: 16};
    4141    const attributes = [attribute0, attribute1];
    42     const input0 = {inputSlot: 0, stride: 20 };
     42    const input0 = {stride: 20, attributeSet: attributes};
    4343    const inputs = [input0];
    44     const inputState = {indexFormat: "uint32", attributes, inputs};
     44    const vertexInput = {vertexBuffers: inputs};
    4545
    4646    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    4949    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    5050
    51     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     51    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    5252    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    5353
  • trunk/LayoutTests/webgpu/whlsl-nested-dot-expression-rvalue.html

    r245721 r245905  
    5151    const depthStencilState = null;
    5252
    53     const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4", offset: 0};
    54     const attribute1 = {shaderLocation: 1, inputSlot: 0, format: "float", offset: 16};
     53    const attribute0 = {shaderLocation: 0, format: "float4"};
     54    const attribute1 = {shaderLocation: 1, format: "float", offset: 16};
    5555    const attributes = [attribute0, attribute1];
    56     const input0 = {inputSlot: 0, stride: 20 };
     56    const input0 = {stride: 20, attributeSet: attributes};
    5757    const inputs = [input0];
    58     const inputState = {indexFormat: "uint32", attributes, inputs};
     58    const vertexInput = {vertexBuffers: inputs};
    5959
    6060    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    6363    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    6464
    65     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     65    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    6666    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    6767
  • trunk/LayoutTests/webgpu/whlsl.html

    r244777 r245905  
    2929    const depthStencilState = null;
    3030   
    31     const attribute0 = {shaderLocation: 0, inputSlot: 0, format: "float4"};
    32     const attribute1 = {shaderLocation: 1, inputSlot: 1, format: "float"};
    33     const attributes = [attribute0, attribute1];
    34     const input0 = {inputSlot: 0, stride: 16 };
    35     const input1 = {inputSlot: 1, stride: 4 };
     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]};
    3635    const inputs = [input0, input1];
    37     const inputState = {indexFormat: "uint32", attributes, inputs};
     36    const vertexInput = {vertexBuffers: inputs};
    3837
    3938    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]};
     
    4241    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
    4342
    44     const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, inputState, sampleCount: 1, layout: pipelineLayout};
     43    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
    4544    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
    4645
  • trunk/Source/WebCore/CMakeLists.txt

    r245638 r245905  
    481481    Modules/webgpu/GPUDepthStencilStateDescriptor.idl
    482482    Modules/webgpu/GPUExtent3D.idl
    483     Modules/webgpu/GPUInputStateDescriptor.idl
    484483    Modules/webgpu/GPULoadOp.idl
    485484    Modules/webgpu/GPUOrigin3D.idl
     
    492491    Modules/webgpu/GPUTextureUsage.idl
    493492    Modules/webgpu/GPUVertexAttributeDescriptor.idl
     493    Modules/webgpu/GPUVertexBufferDescriptor.idl
    494494    Modules/webgpu/GPUVertexInputDescriptor.idl
    495495    Modules/webgpu/NavigatorGPU.idl
  • trunk/Source/WebCore/ChangeLog

    r245900 r245905  
     12019-05-30  Justin Fan  <justin_fan@apple.com>
     2
     3        [Web GPU] Vertex Buffers/Input State API updates
     4        https://bugs.webkit.org/show_bug.cgi?id=194258
     5        <rdar://problem/47806127>
     6
     7        Reviewed by Myles C. Maxfield.
     8
     9        The vertex buffer attributes model for GPURenderPipelines in the WebGPU API has been updated.
     10        Update our implementation to match.
     11
     12        No new tests. Existing tests updated to match new behavior.
     13
     14        * CMakeLists.txt:
     15        * DerivedSources-input.xcfilelist:
     16        * DerivedSources-output.xcfilelist:
     17        * DerivedSources.make:
     18        * Modules/webgpu/GPUVertexAttributeDescriptor.idl:
     19        * Modules/webgpu/GPUVertexBufferDescriptor.idl: Renamed from Source/WebCore/Modules/webgpu/GPUInputStateDescriptor.idl.
     20        * Modules/webgpu/GPUVertexInputDescriptor.idl:
     21        * Modules/webgpu/WebGPURenderPipelineDescriptor.idl:
     22        * Sources.txt:
     23        * WebCore.xcodeproj/project.pbxproj:
     24        * platform/graphics/gpu/GPURenderPipelineDescriptor.h:
     25        * platform/graphics/gpu/GPUVertexAttributeDescriptor.h:
     26        * platform/graphics/gpu/GPUVertexBufferDescriptor.h: Renamed from Source/WebCore/platform/graphics/gpu/GPUInputStateDescriptor.h.
     27        * platform/graphics/gpu/GPUVertexInputDescriptor.h:
     28        * platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm:
     29        (WebCore::trySetVertexInput): Added. Populate Metal and WHLSL pipeline descriptors with vertex attribute metadata.
     30        (WebCore::trySetColorStates): Added. Populate Metal and WHLSL pipeline descriptors with color attachment metadata.
     31        (WebCore::convertLayout): Moved.
     32        (WebCore::trySetMetalFunctions): Moved.
     33        (WebCore::trySetFunctions): Added. WHLSL compilation to Metal SL happens here, then MSL functions are set on pipeline descriptor.
     34        (WebCore::convertRenderPipelineDescriptor): Repurposed. Convert a GPURenderPipelineDescriptor to Metal and WHLSL versions.
     35        (WebCore::tryCreateMtlRenderPipelineState):
     36        (WebCore::GPURenderPipeline::tryCreate):
     37        (WebCore::trySetMetalFunctionsForPipelineDescriptor): Deleted.
     38        (WebCore::trySetWHLSLFunctionsForPipelineDescriptor): Deleted.
     39        (WebCore::trySetFunctionsForPipelineDescriptor): Deleted.
     40        (WebCore::trySetInputStateForPipelineDescriptor): Deleted.
     41        (WebCore::setColorStatesForColorAttachmentArray): Deleted.
     42
    1432019-05-30  Zalan Bujtas  <zalan@apple.com>
    244
  • trunk/Source/WebCore/DerivedSources-input.xcfilelist

    r245638 r245905  
    343343$(PROJECT_DIR)/Modules/webgpu/GPUTextureUsage.idl
    344344$(PROJECT_DIR)/Modules/webgpu/GPUVertexAttributeDescriptor.idl
     345$(PROJECT_DIR)/Modules/webgpu/GPUVertexBufferDescriptor.idl
    345346$(PROJECT_DIR)/Modules/webgpu/GPUVertexInputDescriptor.idl
    346347$(PROJECT_DIR)/Modules/webgpu/NavigatorGPU.idl
  • trunk/Source/WebCore/DerivedSources-output.xcfilelist

    r245638 r245905  
    634634$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexAttributeDescriptor.cpp
    635635$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexAttributeDescriptor.h
     636$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexBufferDescriptor.cpp
     637$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexBufferDescriptor.h
    636638$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexInputDescriptor.cpp
    637639$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSGPUVertexInputDescriptor.h
  • trunk/Source/WebCore/DerivedSources.make

    r245638 r245905  
    389389    $(WebCore)/Modules/webgpu/GPUExtent3D.idl \
    390390    $(WebCore)/Modules/webgpu/GPULoadOp.idl \
    391     $(WebCore)/Modules/webgpu/GPUInputStateDescriptor.idl \
    392391    $(WebCore)/Modules/webgpu/GPUOrigin3D.idl \
    393392    $(WebCore)/Modules/webgpu/GPURequestAdapterOptions.idl \
     
    399398    $(WebCore)/Modules/webgpu/GPUTextureUsage.idl \
    400399    $(WebCore)/Modules/webgpu/GPUVertexAttributeDescriptor.idl \
     400    $(WebCore)/Modules/webgpu/GPUVertexBufferDescriptor.idl \
    401401        $(WebCore)/Modules/webgpu/GPUVertexInputDescriptor.idl \
    402402    $(WebCore)/Modules/webgpu/NavigatorGPU.idl \
  • trunk/Source/WebCore/Modules/webgpu/GPUVertexAttributeDescriptor.idl

    r244442 r245905  
    4141    EnabledAtRuntime=WebGPU
    4242] dictionary GPUVertexAttributeDescriptor {
    43     required u32 shaderLocation;
    44     required u32 inputSlot;
    4543    u64 offset = 0;
    4644    required GPUVertexFormat format;
     45    required u32 shaderLocation;
    4746};
  • trunk/Source/WebCore/Modules/webgpu/GPUVertexBufferDescriptor.idl

    r245904 r245905  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626
    2727typedef unsigned long u32;
     28typedef unsigned long long u64;
    2829
    2930[
    30     ImplementedAs=GPUIndexFormat
    31 ] enum GPUIndexFormat {
    32     "uint16",
    33     "uint32"
     31    ImplementedAs=GPUInputStepMode
     32] enum GPUInputStepMode {
     33    "vertex",
     34    "instance"
    3435};
    3536
     
    3738    Conditional=WEBGPU,
    3839    EnabledAtRuntime=WebGPU
    39 ] dictionary GPUInputStateDescriptor {
    40     GPUIndexFormat? indexFormat;
    41 
    42     required sequence<GPUVertexAttributeDescriptor> attributes;
    43     required sequence<GPUVertexInputDescriptor> inputs;
     40] dictionary GPUVertexBufferDescriptor {
     41    required u64 stride;
     42    GPUInputStepMode stepMode = "vertex";
     43    sequence<GPUVertexAttributeDescriptor> attributeSet;
    4444};
  • trunk/Source/WebCore/Modules/webgpu/GPUVertexInputDescriptor.idl

    r244442 r245905  
    2626
    2727typedef unsigned long u32;
    28 typedef unsigned long long u64;
    2928
    3029[
    31     ImplementedAs=GPUInputStepMode
    32 ] enum GPUInputStepMode {
    33     "vertex",
    34     "instance"
     30    ImplementedAs=GPUIndexFormat
     31] enum GPUIndexFormat {
     32    "uint16",
     33    "uint32"
    3534};
    3635
     
    3938    EnabledAtRuntime=WebGPU
    4039] dictionary GPUVertexInputDescriptor {
    41     required u32 inputSlot;
    42     required u64 stride;
    43     GPUInputStepMode stepMode = "vertex";
     40    GPUIndexFormat indexFormat = "uint32";
     41    required sequence<GPUVertexBufferDescriptor?> vertexBuffers;
    4442};
  • trunk/Source/WebCore/Modules/webgpu/WebGPURenderPipelineDescriptor.idl

    r244442 r245905  
    4545    required sequence<GPUColorStateDescriptor> colorStates;
    4646    GPUDepthStencilStateDescriptor? depthStencilState = null;
    47     required GPUInputStateDescriptor inputState;
     47    required GPUVertexInputDescriptor vertexInput;
    4848};
  • trunk/Source/WebCore/Sources.txt

    r245850 r245905  
    27482748JSGPUDepthStencilStateDescriptor.cpp
    27492749JSGPUExtent3D.cpp
    2750 JSGPUInputStateDescriptor.cpp
    27512750JSGPULoadOp.cpp
    27522751JSGPUOrigin3D.cpp
     
    27592758JSGPUTextureUsage.cpp
    27602759JSGPUVertexAttributeDescriptor.cpp
     2760JSGPUVertexBufferDescriptor.cpp
    27612761JSGPUVertexInputDescriptor.cpp
    27622762JSGainNode.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r245850 r245905  
    1402914029                D0D8649121B760C4003C983C /* GPUBufferMetal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GPUBufferMetal.mm; sourceTree = "<group>"; };
    1403014030                D0D8649221B760F2003C983C /* GPUBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUBuffer.h; sourceTree = "<group>"; };
    14031                 D0D8649421BA173D003C983C /* GPUInputStateDescriptor.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUInputStateDescriptor.idl; sourceTree = "<group>"; };
     14031                D0D8649421BA173D003C983C /* GPUVertexInputDescriptor.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUVertexInputDescriptor.idl; sourceTree = "<group>"; };
    1403214032                D0D8649621BA18F4003C983C /* GPUVertexAttributeDescriptor.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUVertexAttributeDescriptor.idl; sourceTree = "<group>"; };
    14033                 D0D8649821BA19A7003C983C /* GPUVertexInputDescriptor.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUVertexInputDescriptor.idl; sourceTree = "<group>"; };
    14034                 D0D8649921BA1B1F003C983C /* GPUInputStateDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUInputStateDescriptor.h; sourceTree = "<group>"; };
     14033                D0D8649821BA19A7003C983C /* GPUVertexBufferDescriptor.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = GPUVertexBufferDescriptor.idl; sourceTree = "<group>"; };
     14034                D0D8649921BA1B1F003C983C /* GPUVertexInputDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUVertexInputDescriptor.h; sourceTree = "<group>"; };
    1403514035                D0D8649B21BA1C2D003C983C /* GPUVertexAttributeDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUVertexAttributeDescriptor.h; sourceTree = "<group>"; };
    14036                 D0D8649C21BA1CE8003C983C /* GPUVertexInputDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUVertexInputDescriptor.h; sourceTree = "<group>"; };
     14036                D0D8649C21BA1CE8003C983C /* GPUVertexBufferDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUVertexBufferDescriptor.h; sourceTree = "<group>"; };
    1403714037                D0DA0BE4217930E2007FE2AC /* WebGPUSwapChain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGPUSwapChain.h; sourceTree = "<group>"; };
    1403814038                D0DA0BE5217930E2007FE2AC /* WebGPUSwapChain.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebGPUSwapChain.cpp; sourceTree = "<group>"; };
     
    1826618266                                312FF8BE21A4C2F100EB199D /* GPUDevice.h */,
    1826718267                                D026F47D220A2AC600AC5F49 /* GPUExtent3D.h */,
    18268                                 D0D8649921BA1B1F003C983C /* GPUInputStateDescriptor.h */,
    1826918268                                D0F7559F2203BA1400118058 /* GPULimits.h */,
    1827018269                                D08AA02F220D0BD50058C502 /* GPULoadOp.h */,
     
    1829518294                                D06EF552220BA26A0018724E /* GPUUtils.h */,
    1829618295                                D0D8649B21BA1C2D003C983C /* GPUVertexAttributeDescriptor.h */,
    18297                                 D0D8649C21BA1CE8003C983C /* GPUVertexInputDescriptor.h */,
     18296                                D0D8649C21BA1CE8003C983C /* GPUVertexBufferDescriptor.h */,
     18297                                D0D8649921BA1B1F003C983C /* GPUVertexInputDescriptor.h */,
    1829818298                                498770D71242C535002226BA /* Texture.cpp */,
    1829918299                                498770D81242C535002226BA /* Texture.h */,
     
    2584825848                                D03C84A221FFD7230002227F /* GPUDepthStencilStateDescriptor.idl */,
    2584925849                                D026F480220A2B7000AC5F49 /* GPUExtent3D.idl */,
    25850                                 D0D8649421BA173D003C983C /* GPUInputStateDescriptor.idl */,
    2585125850                                D08AA02D220D0B9C0058C502 /* GPULoadOp.idl */,
    2585225851                                D0CCA94922299F97006979B6 /* GPUOrigin3D.h */,
     
    2586125860                                D026F483220A472F00AC5F49 /* GPUTextureUsage.idl */,
    2586225861                                D0D8649621BA18F4003C983C /* GPUVertexAttributeDescriptor.idl */,
    25863                                 D0D8649821BA19A7003C983C /* GPUVertexInputDescriptor.idl */,
     25862                                D0D8649821BA19A7003C983C /* GPUVertexBufferDescriptor.idl */,
     25863                                D0D8649421BA173D003C983C /* GPUVertexInputDescriptor.idl */,
    2586425864                                D00487ED2274281300EED7D9 /* NavigatorGPU.cpp */,
    2586525865                                D00487EE2274281400EED7D9 /* NavigatorGPU.h */,
  • trunk/Source/WebCore/platform/graphics/gpu/GPURenderPipelineDescriptor.h

    r244442 r245905  
    3030#include "GPUColorStateDescriptor.h"
    3131#include "GPUDepthStencilStateDescriptor.h"
    32 #include "GPUInputStateDescriptor.h"
    3332#include "GPUPipelineDescriptorBase.h"
    3433#include "GPUPipelineStageDescriptor.h"
     34#include "GPUVertexInputDescriptor.h"
    3535#include <wtf/Optional.h>
    3636#include <wtf/Vector.h>
     
    5050    Vector<GPUColorStateDescriptor> colorStates;
    5151    Optional<GPUDepthStencilStateDescriptor> depthStencilState;
    52     GPUInputStateDescriptor inputState;
     52    GPUVertexInputDescriptor vertexInput;
    5353};
    5454
  • trunk/Source/WebCore/platform/graphics/gpu/GPUVertexAttributeDescriptor.h

    r243658 r245905  
    4040
    4141struct GPUVertexAttributeDescriptor {
    42     unsigned shaderLocation;
    43     unsigned inputSlot;
    4442    uint64_t offset;
    4543    GPUVertexFormat format;
     44    unsigned shaderLocation;
    4645};
    4746
  • trunk/Source/WebCore/platform/graphics/gpu/GPUVertexBufferDescriptor.h

    r245904 r245905  
    11/*
    2  * Copyright (C) 2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929
    3030#include "GPUVertexAttributeDescriptor.h"
    31 #include "GPUVertexInputDescriptor.h"
    3231#include <wtf/Vector.h>
    3332
    3433namespace WebCore {
    3534
    36 enum class GPUIndexFormat {
    37     Uint16,
    38     Uint32,
     35enum class GPUInputStepMode {
     36    Vertex,
     37    Instance,
    3938};
    4039
    41 struct GPUInputStateDescriptor {
    42     Optional<GPUIndexFormat> indexFormat;
    43 
    44     Vector<GPUVertexAttributeDescriptor> attributes;
    45     Vector<GPUVertexInputDescriptor> inputs;
     40struct GPUVertexBufferDescriptor {
     41    uint64_t stride;
     42    GPUInputStepMode stepMode;
     43    Vector<GPUVertexAttributeDescriptor> attributeSet;
    4644};
    4745
  • trunk/Source/WebCore/platform/graphics/gpu/GPUVertexInputDescriptor.h

    r243658 r245905  
    2828#if ENABLE(WEBGPU)
    2929
     30#include "GPUVertexBufferDescriptor.h"
     31#include <wtf/Vector.h>
     32
    3033namespace WebCore {
    3134
    32 enum class GPUInputStepMode {
    33     Vertex,
    34     Instance,
     35enum class GPUIndexFormat {
     36    Uint16,
     37    Uint32,
    3538};
    3639
    3740struct GPUVertexInputDescriptor {
    38     unsigned inputSlot;
    39     uint64_t stride;
    40     GPUInputStepMode stepMode;
     41    GPUIndexFormat indexFormat;
     42    Vector<Optional<GPUVertexBufferDescriptor>> vertexBuffers;
    4143};
    4244
  • trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm

    r245759 r245905  
    3838#import <wtf/BlockObjCExceptions.h>
    3939#import <wtf/CheckedArithmetic.h>
     40#import <wtf/HashSet.h>
    4041#import <wtf/OptionSet.h>
    4142#import <wtf/Optional.h>
     
    146147}
    147148
    148 static Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout& layout)
    149 {
    150     WHLSL::Layout result;
    151     if (layout.bindGroupLayouts().size() > std::numeric_limits<unsigned>::max())
    152         return WTF::nullopt;
    153     for (size_t i = 0; i < layout.bindGroupLayouts().size(); ++i) {
    154         const auto& bindGroupLayout = layout.bindGroupLayouts()[i];
    155         WHLSL::BindGroup bindGroup;
    156         bindGroup.name = static_cast<unsigned>(i);
    157         for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) {
    158             const auto& gpuBindGroupLayoutBinding = keyValuePair.value;
    159             WHLSL::Binding binding;
    160             binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility);
    161             if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type))
    162                 binding.bindingType = *bindingType;
    163             else
    164                 return WTF::nullopt;
    165             if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max())
    166                 return WTF::nullopt;
    167             binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding);
    168             bindGroup.bindings.append(WTFMove(binding));
    169         }
    170         result.append(WTFMove(bindGroup));
    171     }
    172     return result;
    173 }
    174 
    175 static Optional<WHLSL::RenderPipelineDescriptor> convertRenderPipelineDescriptor(const GPURenderPipelineDescriptor& descriptor)
    176 {
    177     WHLSL::RenderPipelineDescriptor whlslDescriptor;
    178     if (descriptor.inputState.attributes.size() > std::numeric_limits<unsigned>::max())
    179         return WTF::nullopt;
    180     if (descriptor.colorStates.size() > std::numeric_limits<unsigned>::max())
    181         return WTF::nullopt;
    182 
    183     for (size_t i = 0; i < descriptor.inputState.attributes.size(); ++i)
    184         whlslDescriptor.vertexAttributes.append({ convertVertexFormat(descriptor.inputState.attributes[i].format), descriptor.inputState.attributes[i].shaderLocation, static_cast<unsigned>(i) });
    185 
    186     for (size_t i = 0; i < descriptor.colorStates.size(); ++i) {
    187         if (auto format = convertTextureFormat(descriptor.colorStates[i].format))
    188             whlslDescriptor.attachmentsStateDescriptor.attachmentDescriptors.append({*format, static_cast<unsigned>(i)});
    189         else
    190             return WTF::nullopt;
    191     }
    192 
    193     // FIXME: depthStencilAttachmentDescriptor isn't implemented yet.
    194 
    195     if (descriptor.layout) {
    196         if (auto layout = convertLayout(*descriptor.layout))
    197             whlslDescriptor.layout = WTFMove(*layout);
    198         else
    199             return WTF::nullopt;
    200     }
    201     whlslDescriptor.vertexEntryPointName = descriptor.vertexStage.entryPoint;
    202     if (descriptor.fragmentStage)
    203         whlslDescriptor.fragmentEntryPointName = descriptor.fragmentStage->entryPoint;
    204     return whlslDescriptor;
    205 }
    206 
    207 static bool trySetMetalFunctionsForPipelineDescriptor(const char* const functionName, MTLLibrary *vertexMetalLibrary, MTLLibrary *fragmentMetalLibrary, MTLRenderPipelineDescriptor *mtlDescriptor, const String& vertexEntryPointName, const String& fragmentEntryPointName)
    208 {
    209 #if LOG_DISABLED
    210     UNUSED_PARAM(functionName);
    211 #endif
    212 
    213     {
    214         BEGIN_BLOCK_OBJC_EXCEPTIONS;
    215 
    216         // Metal requires a vertex shader in all render pipelines.
    217         if (!vertexMetalLibrary) {
    218             LOG(WebGPU, "%s: MTLLibrary for vertex stage does not exist!", functionName);
    219             return false;
    220         }
    221 
    222         auto function = adoptNS([vertexMetalLibrary newFunctionWithName:vertexEntryPointName]);
    223         if (!function) {
    224             LOG(WebGPU, "%s: Cannot create vertex MTLFunction \"%s\"!", functionName, vertexEntryPointName.utf8().data());
    225             return false;
    226         }
    227 
    228         [mtlDescriptor setVertexFunction:function.get()];
    229 
    230         END_BLOCK_OBJC_EXCEPTIONS;
    231     }
    232 
    233     {
    234         BEGIN_BLOCK_OBJC_EXCEPTIONS;
    235 
    236         // However, fragment shaders are optional.
    237         if (!fragmentMetalLibrary)
    238             return true;
    239 
    240         auto function = adoptNS([fragmentMetalLibrary newFunctionWithName:fragmentEntryPointName]);
    241 
    242         if (!function) {
    243             LOG(WebGPU, "%s: Cannot create fragment MTLFunction \"%s\"!", functionName, fragmentEntryPointName.utf8().data());
    244             return false;
    245         }
    246 
    247         [mtlDescriptor setFragmentFunction:function.get()];
    248         return true;
    249 
    250         END_BLOCK_OBJC_EXCEPTIONS;
    251     }
    252 
    253     return false;
    254 }
    255 
    256 static bool trySetWHLSLFunctionsForPipelineDescriptor(const char* const functionName, MTLRenderPipelineDescriptor *mtlDescriptor, const GPURenderPipelineDescriptor& descriptor, String whlslSource, const GPUDevice& device)
    257 {
    258     auto whlslDescriptor = convertRenderPipelineDescriptor(descriptor);
    259     if (!whlslDescriptor)
    260         return false;
    261 
    262     auto result = WHLSL::prepare(whlslSource, *whlslDescriptor);
    263     if (!result)
    264         return false;
    265 
    266     WTFLogAlways("Metal Source: %s", result->metalSource.utf8().data());
    267 
    268     NSError *error = nil;
    269     auto library = adoptNS([device.platformDevice() newLibraryWithSource:result->metalSource options:nil error:&error]);
    270     ASSERT(library);
    271     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195771 Once we zero-fill variables, there should be no warnings, so we should be able to ASSERT(!error) here.
    272 
    273     return trySetMetalFunctionsForPipelineDescriptor(functionName, library.get(), library.get(), mtlDescriptor, result->mangledVertexEntryPointName, result->mangledFragmentEntryPointName);
    274 }
    275 
    276 static bool trySetFunctionsForPipelineDescriptor(const char* const functionName, MTLRenderPipelineDescriptor *mtlDescriptor, const GPURenderPipelineDescriptor& descriptor, const GPUDevice& device)
    277 {
    278     const auto& vertexStage = descriptor.vertexStage;
    279     const auto& fragmentStage = descriptor.fragmentStage;
    280 
    281     const auto& whlslSource = vertexStage.module->whlslSource();
    282     if (!whlslSource.isNull()) {
    283         if (!fragmentStage || vertexStage.module.ptr() == fragmentStage->module.ptr()) {
    284             // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195446 Allow WHLSL shaders to come from different programs.
    285             return trySetWHLSLFunctionsForPipelineDescriptor(functionName, mtlDescriptor, descriptor, whlslSource, device);
    286         }
    287     }
    288 
    289     auto vertexLibrary = vertexStage.module->platformShaderModule();
    290     MTLLibrary *fragmentLibrary = nil;
    291     String fragmentEntryPoint;
    292     if (fragmentStage) {
    293         fragmentLibrary = fragmentStage->module->platformShaderModule();
    294         fragmentEntryPoint = fragmentStage->entryPoint;
    295     }
    296 
    297     return trySetMetalFunctionsForPipelineDescriptor(functionName, vertexLibrary, fragmentLibrary, mtlDescriptor, vertexStage.entryPoint, fragmentEntryPoint);
    298 }
    299 
    300149static MTLVertexFormat mtlVertexFormatForGPUVertexFormat(GPUVertexFormat format)
    301150{
     
    326175}
    327176
    328 static bool trySetInputStateForPipelineDescriptor(const char* const functionName, MTLRenderPipelineDescriptor *mtlDescriptor, const GPUInputStateDescriptor& descriptor)
     177// FIXME: Move this into GPULimits when that is implemented properly.
     178constexpr unsigned maxVertexAttributes = 16;
     179
     180static bool trySetVertexInput(const char* const functionName, const GPUVertexInputDescriptor& descriptor, MTLRenderPipelineDescriptor *mtlDescriptor, Optional<WHLSL::RenderPipelineDescriptor>& whlslDescriptor)
    329181{
    330182#if LOG_DISABLED
    331183    UNUSED_PARAM(functionName);
    332184#endif
     185    const auto& buffers = descriptor.vertexBuffers;
     186
     187    if (buffers.size() > maxVertexBuffers) {
     188        LOG(WebGPU, "%s: Too many vertex input buffers!", functionName);
     189        return false;
     190    }
     191
    333192    auto mtlVertexDescriptor = adoptNS([MTLVertexDescriptor new]);
    334193
    335     const auto& attributes = descriptor.attributes;
    336 
     194    auto layoutArray = retainPtr(mtlVertexDescriptor.get().layouts);
    337195    auto attributeArray = retainPtr(mtlVertexDescriptor.get().attributes);
    338196
    339     for (size_t i = 0; i < attributes.size(); ++i) {
    340         auto location = static_cast<unsigned>(i);
    341         // Maximum number of vertex attributes to be supported by Web GPU.
    342         if (location >= 16) {
    343             LOG(WebGPU, "%s: Invalid shaderLocation %u for vertex attribute!", functionName, location);
     197    // Attribute shaderLocations must be uniquely flat-mapped to [0, {max number of vertex attributes}].
     198    unsigned attributeIndex = 0;
     199    HashSet<unsigned, IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> locations;
     200
     201    for (size_t index = 0; index < buffers.size(); ++index) {
     202        if (!buffers[index])
     203            continue;
     204
     205        const auto& attributes = buffers[index]->attributeSet;
     206
     207        if (attributes.size() + attributeIndex > maxVertexAttributes) {
     208            LOG(WebGPU, "%s: Too many vertex attributes!", functionName);
    344209            return false;
    345210        }
    346         if (attributes[i].inputSlot >= maxVertexBuffers) {
    347             LOG(WebGPU, "%s: Invalid inputSlot %u for vertex attribute %u!", functionName, attributes[i].inputSlot, location);
     211
     212        NSUInteger inputStride = 0;
     213        if (!WTF::convertSafely(buffers[index]->stride, inputStride)) {
     214            LOG(WebGPU, "%s: Stride for vertex input buffer %u is too large!", functionName, index);
    348215            return false;
    349216        }
    350         // MTLBuffer size (NSUInteger) is 32 bits on some platforms.
    351         // FIXME: Ensure offset < buffer's stride + format's data size.
    352         NSUInteger attributeOffset = 0;
    353         if (!WTF::convertSafely(attributes[i].offset, attributeOffset)) {
    354             LOG(WebGPU, "%s: Buffer offset for vertex attribute %u is too large!", functionName, location);
    355             return false;
    356         }
    357 
    358         auto mtlAttributeDesc = retainPtr([attributeArray objectAtIndexedSubscript:location]);
    359         [mtlAttributeDesc setFormat:mtlVertexFormatForGPUVertexFormat(attributes[i].format)];
    360         [mtlAttributeDesc setOffset:attributeOffset];
    361         [mtlAttributeDesc setBufferIndex:WHLSL::Metal::calculateVertexBufferIndex(attributes[i].inputSlot)];
    362     }
    363 
    364     const auto& inputs = descriptor.inputs;
    365 
    366     auto layoutArray = retainPtr(mtlVertexDescriptor.get().layouts);
    367 
    368     for (size_t j = 0; j < inputs.size(); ++j) {
    369         auto slot = inputs[j].inputSlot;
    370         if (slot >= maxVertexBuffers) {
    371             LOG(WebGPU, "%s: Invalid inputSlot %d for vertex buffer!", functionName, slot);
    372             return false;
    373         }
    374         NSUInteger inputStride = 0;
    375         if (!WTF::convertSafely(inputs[j].stride, inputStride)) {
    376             LOG(WebGPU, "%s: Stride for vertex buffer slot %d is too large!", functionName, slot);
    377             return false;
    378         }
    379 
    380         auto convertedSlot = WHLSL::Metal::calculateVertexBufferIndex(slot);
    381         auto mtlLayoutDesc = retainPtr([layoutArray objectAtIndexedSubscript:convertedSlot]);
    382         [mtlLayoutDesc setStepFunction:mtlStepFunctionForGPUInputStepMode(inputs[j].stepMode)];
     217
     218        auto convertedBufferIndex = WHLSL::Metal::calculateVertexBufferIndex(index);
     219
     220        BEGIN_BLOCK_OBJC_EXCEPTIONS;
     221        auto mtlLayoutDesc = retainPtr([layoutArray objectAtIndexedSubscript:convertedBufferIndex]);
     222        [mtlLayoutDesc setStepFunction:mtlStepFunctionForGPUInputStepMode(buffers[index]->stepMode)];
    383223        [mtlLayoutDesc setStride:inputStride];
     224        END_BLOCK_OBJC_EXCEPTIONS;
     225
     226        for (const auto& attribute : attributes) {
     227            if (!locations.add(attribute.shaderLocation).isNewEntry) {
     228                LOG(WebGPU, "%s: Duplicate shaderLocation %u for vertex attribute!", functionName, attribute.shaderLocation);
     229                return false;
     230            }
     231
     232            NSUInteger offset = 0;
     233            if (!WTF::convertSafely(attribute.offset, offset)) {
     234                LOG(WebGPU, "%s: Buffer offset for vertex attribute %u is too large!", functionName, attribute.shaderLocation);
     235                return false;
     236            }
     237
     238            BEGIN_BLOCK_OBJC_EXCEPTIONS;
     239            auto mtlAttributeDesc = retainPtr([attributeArray objectAtIndexedSubscript:attributeIndex]);
     240            [mtlAttributeDesc setFormat:mtlVertexFormatForGPUVertexFormat(attribute.format)];
     241            [mtlAttributeDesc setOffset:offset];
     242            [mtlAttributeDesc setBufferIndex:convertedBufferIndex];
     243            END_BLOCK_OBJC_EXCEPTIONS;
     244
     245            if (whlslDescriptor)
     246                whlslDescriptor->vertexAttributes.append({ convertVertexFormat(attribute.format), attribute.shaderLocation, attributeIndex });
     247
     248            ++attributeIndex;
     249        }
    384250    }
    385251
     
    461327}
    462328
    463 static void setColorStatesForColorAttachmentArray(MTLRenderPipelineColorAttachmentDescriptorArray* array, const Vector<GPUColorStateDescriptor>& colorStates)
    464 {
     329static bool trySetColorStates(const char* const functionName, const Vector<GPUColorStateDescriptor>& colorStates, MTLRenderPipelineColorAttachmentDescriptorArray* array, Optional<WHLSL::RenderPipelineDescriptor>& whlslDescriptor)
     330{
     331#if LOG_DISABLED
     332    UNUSED_PARAM(functionName);
     333#endif
     334    // FIXME: Replace with maximum number of color attachments per render pass from GPULimits.
     335    if (colorStates.size() > 4) {
     336        LOG(WebGPU, "%s: Invalid number of GPUColorStateDescriptors!", functionName);
     337        return false;
     338    }
     339
     340    BEGIN_BLOCK_OBJC_EXCEPTIONS;
     341
    465342    for (unsigned i = 0; i < colorStates.size(); ++i) {
    466343        auto& state = colorStates[i];
     
    475352        [descriptor setSourceAlphaBlendFactor:mtlBlendFactorForGPUBlendFactor(state.alphaBlend.srcFactor)];
    476353        [descriptor setSourceRGBBlendFactor:mtlBlendFactorForGPUBlendFactor(state.colorBlend.srcFactor)];
    477     }
    478 }
    479 
    480 static RetainPtr<MTLRenderPipelineState> tryCreateMtlRenderPipelineState(const char* const functionName, const GPURenderPipelineDescriptor& descriptor, const GPUDevice& device)
     354
     355        if (whlslDescriptor) {
     356            if (auto format = convertTextureFormat(state.format))
     357                whlslDescriptor->attachmentsStateDescriptor.attachmentDescriptors.append({*format, i});
     358            else {
     359                LOG(WebGPU, "%s: Invalid texture format for color attachment %u!", functionName, i);
     360                return false;
     361            }
     362        }
     363    }
     364
     365    END_BLOCK_OBJC_EXCEPTIONS;
     366
     367    return true;
     368}
     369
     370static Optional<WHLSL::Layout> convertLayout(const GPUPipelineLayout& layout)
     371{
     372    WHLSL::Layout result;
     373    if (layout.bindGroupLayouts().size() > std::numeric_limits<unsigned>::max())
     374        return WTF::nullopt;
     375    for (size_t i = 0; i < layout.bindGroupLayouts().size(); ++i) {
     376        const auto& bindGroupLayout = layout.bindGroupLayouts()[i];
     377        WHLSL::BindGroup bindGroup;
     378        bindGroup.name = static_cast<unsigned>(i);
     379        for (const auto& keyValuePair : bindGroupLayout->bindingsMap()) {
     380            const auto& gpuBindGroupLayoutBinding = keyValuePair.value;
     381            WHLSL::Binding binding;
     382            binding.visibility = convertShaderStageFlags(gpuBindGroupLayoutBinding.visibility);
     383            if (auto bindingType = convertBindingType(gpuBindGroupLayoutBinding.type))
     384                binding.bindingType = *bindingType;
     385            else
     386                return WTF::nullopt;
     387            if (gpuBindGroupLayoutBinding.binding > std::numeric_limits<unsigned>::max())
     388                return WTF::nullopt;
     389            binding.name = static_cast<unsigned>(gpuBindGroupLayoutBinding.binding);
     390            bindGroup.bindings.append(WTFMove(binding));
     391        }
     392        result.append(WTFMove(bindGroup));
     393    }
     394    return result;
     395}
     396
     397static bool trySetMetalFunctions(const char* const functionName, MTLLibrary *vertexMetalLibrary, MTLLibrary *fragmentMetalLibrary, MTLRenderPipelineDescriptor *mtlDescriptor, const String& vertexEntryPointName, const String& fragmentEntryPointName)
     398{
     399#if LOG_DISABLED
     400    UNUSED_PARAM(functionName);
     401#endif
     402
     403    {
     404        BEGIN_BLOCK_OBJC_EXCEPTIONS;
     405
     406        // Metal requires a vertex shader in all render pipelines.
     407        if (!vertexMetalLibrary) {
     408            LOG(WebGPU, "%s: MTLLibrary for vertex stage does not exist!", functionName);
     409            return false;
     410        }
     411
     412        auto function = adoptNS([vertexMetalLibrary newFunctionWithName:vertexEntryPointName]);
     413        if (!function) {
     414            LOG(WebGPU, "%s: Cannot create vertex MTLFunction \"%s\"!", functionName, vertexEntryPointName.utf8().data());
     415            return false;
     416        }
     417
     418        [mtlDescriptor setVertexFunction:function.get()];
     419
     420        END_BLOCK_OBJC_EXCEPTIONS;
     421    }
     422
     423    {
     424        BEGIN_BLOCK_OBJC_EXCEPTIONS;
     425
     426        // However, fragment shaders are optional.
     427        if (!fragmentMetalLibrary)
     428            return true;
     429
     430        auto function = adoptNS([fragmentMetalLibrary newFunctionWithName:fragmentEntryPointName]);
     431
     432        if (!function) {
     433            LOG(WebGPU, "%s: Cannot create fragment MTLFunction \"%s\"!", functionName, fragmentEntryPointName.utf8().data());
     434            return false;
     435        }
     436
     437        [mtlDescriptor setFragmentFunction:function.get()];
     438        return true;
     439
     440        END_BLOCK_OBJC_EXCEPTIONS;
     441    }
     442
     443    return false;
     444}
     445
     446static bool trySetFunctions(const char* const functionName, const GPUPipelineStageDescriptor& vertexStage, const Optional<GPUPipelineStageDescriptor>& fragmentStage, const GPUDevice& device, MTLRenderPipelineDescriptor* mtlDescriptor, Optional<WHLSL::RenderPipelineDescriptor>& whlslDescriptor)
     447{
     448#if LOG_DISABLED
     449    UNUSED_PARAM(functionName);
     450#endif
     451    RetainPtr<MTLLibrary> vertexLibrary, fragmentLibrary;
     452    String vertexEntryPoint, fragmentEntryPoint;
     453
     454    if (whlslDescriptor) {
     455        // WHLSL functions are compiled to MSL first.
     456        String whlslSource = vertexStage.module->whlslSource();
     457        ASSERT(!whlslSource.isNull());
     458
     459        whlslDescriptor->vertexEntryPointName = vertexStage.entryPoint;
     460        if (fragmentStage)
     461            whlslDescriptor->fragmentEntryPointName = fragmentStage->entryPoint;
     462
     463        auto whlslCompileResult = WHLSL::prepare(whlslSource, *whlslDescriptor);
     464        if (!whlslCompileResult)
     465            return false;
     466
     467        WTFLogAlways("Metal Source: %s", whlslCompileResult->metalSource.utf8().data());
     468
     469        NSError *error = nil;
     470
     471        BEGIN_BLOCK_OBJC_EXCEPTIONS;
     472        vertexLibrary = adoptNS([device.platformDevice() newLibraryWithSource:whlslCompileResult->metalSource options:nil error:&error]);
     473        END_BLOCK_OBJC_EXCEPTIONS;
     474
     475        ASSERT(vertexLibrary);
     476        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195771 Once we zero-fill variables, there should be no warnings, so we should be able to ASSERT(!error) here.
     477
     478        fragmentLibrary = vertexLibrary;
     479        vertexEntryPoint = whlslCompileResult->mangledVertexEntryPointName;
     480        fragmentEntryPoint = whlslCompileResult->mangledFragmentEntryPointName;
     481    } else {
     482        vertexLibrary = vertexStage.module->platformShaderModule();
     483        vertexEntryPoint = vertexStage.entryPoint;
     484        if (fragmentStage) {
     485            fragmentLibrary = fragmentStage->module->platformShaderModule();
     486            fragmentEntryPoint = fragmentStage->entryPoint;
     487        }
     488    }
     489
     490    return trySetMetalFunctions(functionName, vertexLibrary.get(), fragmentLibrary.get(), mtlDescriptor, vertexEntryPoint, fragmentEntryPoint);
     491}
     492
     493static RetainPtr<MTLRenderPipelineDescriptor> convertRenderPipelineDescriptor(const char* const functionName, const GPURenderPipelineDescriptor& descriptor, const GPUDevice& device)
    481494{
    482495    RetainPtr<MTLRenderPipelineDescriptor> mtlDescriptor;
     
    493506    }
    494507
    495     bool didSetFunctions = false, didSetInputState = false;
    496 
    497     BEGIN_BLOCK_OBJC_EXCEPTIONS;
    498 
    499     didSetFunctions = trySetFunctionsForPipelineDescriptor(functionName, mtlDescriptor.get(), descriptor, device);
    500     didSetInputState = trySetInputStateForPipelineDescriptor(functionName, mtlDescriptor.get(), descriptor.inputState);
    501     setColorStatesForColorAttachmentArray(mtlDescriptor.get().colorAttachments, descriptor.colorStates);
    502 
    503     END_BLOCK_OBJC_EXCEPTIONS;
    504 
    505     if (!didSetFunctions || !didSetInputState)
     508    // Determine if shader source is in WHLSL or MSL.
     509    const auto& vertexStage = descriptor.vertexStage;
     510    const auto& fragmentStage = descriptor.fragmentStage;
     511
     512    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195446 Allow WHLSL shaders to come from different programs.
     513    bool isWhlsl = !vertexStage.module->whlslSource().isNull() && (!fragmentStage || vertexStage.module.ptr() == fragmentStage->module.ptr());
     514
     515    // Set data for the Metal pipeline descriptor (and WHLSL's, if needed).
     516    Optional<WHLSL::RenderPipelineDescriptor> whlslDescriptor;
     517    if (isWhlsl)
     518        whlslDescriptor = WHLSL::RenderPipelineDescriptor();
     519
     520    if (!trySetVertexInput(functionName, descriptor.vertexInput, mtlDescriptor.get(), whlslDescriptor))
     521        return nullptr;
     522
     523    if (!trySetColorStates(functionName, descriptor.colorStates, mtlDescriptor.get().colorAttachments, whlslDescriptor))
     524        return nullptr;
     525
     526    if (descriptor.layout && whlslDescriptor) {
     527        if (auto layout = convertLayout(*descriptor.layout))
     528            whlslDescriptor->layout = WTFMove(*layout);
     529        else {
     530            LOG(WebGPU, "%s: Error converting GPUPipelineLayout!", functionName);
     531            return nullptr;
     532        }
     533    }
     534
     535    if (!trySetFunctions(functionName, vertexStage, fragmentStage, device, mtlDescriptor.get(), whlslDescriptor))
     536        return nullptr;
     537
     538    return mtlDescriptor;
     539}
     540
     541static RetainPtr<MTLRenderPipelineState> tryCreateMtlRenderPipelineState(const char* const functionName, const GPURenderPipelineDescriptor& descriptor, const GPUDevice& device)
     542{
     543    auto mtlDescriptor = convertRenderPipelineDescriptor(functionName, descriptor, device);
     544    if (!mtlDescriptor)
    506545        return nullptr;
    507546
     
    534573        return nullptr;
    535574
     575    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198387 depthStencilAttachmentDescriptor isn't implemented yet for WHLSL compiler.
     576
    536577    auto pipeline = tryCreateMtlRenderPipelineState(functionName, descriptor, device);
    537578    if (!pipeline)
    538579        return nullptr;
    539580
    540     return adoptRef(new GPURenderPipeline(WTFMove(depthStencil), WTFMove(pipeline), descriptor.primitiveTopology, descriptor.inputState.indexFormat));
     581    return adoptRef(new GPURenderPipeline(WTFMove(depthStencil), WTFMove(pipeline), descriptor.primitiveTopology, descriptor.vertexInput.indexFormat));
    541582}
    542583
Note: See TracChangeset for help on using the changeset viewer.