Title: [249214] trunk
Revision
249214
Author
mmaxfi...@apple.com
Date
2019-08-28 12:46:36 -0700 (Wed, 28 Aug 2019)

Log Message

[WHLSL] Matrices need to have correct alignment
https://bugs.webkit.org/show_bug.cgi?id=201212

Reviewed by Robin Morisset.

Source/WebCore:

Matrices have particular alignment requirements and size requirements.

  Type   | Alignment | Size
---------------------------
float2x2 |         8 |   16
float2x3 |        16 |   32
float2x4 |        16 |   32
float3x2 |         8 |   24
float3x3 |        16 |   48
float3x4 |        16 |   48
float4x2 |         8 |   32
float4x3 |        16 |   64
float4x4 |        16 |   64

These are important because they may be a member of a struct, and we don't want to misplace
every successive item in the struct.

Test: webgpu/whlsl/matrix-alignment.html

* Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp:
(WebCore::WHLSL::Metal::writeNativeType):

LayoutTests:

Test the alignment and size of float matrices.

Intentionally don't test bool matrices, because they can't be placed in buffers,
meaning their size and alignment is unobservable.

* webgpu/whlsl/matrix-alignment-expected.txt: Added.
* webgpu/whlsl/matrix-alignment.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (249213 => 249214)


--- trunk/LayoutTests/ChangeLog	2019-08-28 19:36:23 UTC (rev 249213)
+++ trunk/LayoutTests/ChangeLog	2019-08-28 19:46:36 UTC (rev 249214)
@@ -1,3 +1,18 @@
+2019-08-28  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [WHLSL] Matrices need to have correct alignment
+        https://bugs.webkit.org/show_bug.cgi?id=201212
+
+        Reviewed by Robin Morisset.
+
+        Test the alignment and size of float matrices.
+
+        Intentionally don't test bool matrices, because they can't be placed in buffers,
+        meaning their size and alignment is unobservable.
+
+        * webgpu/whlsl/matrix-alignment-expected.txt: Added.
+        * webgpu/whlsl/matrix-alignment.html: Added.
+
 2019-08-28  Rob Buis  <rb...@igalia.com>
 
         Implement HTMLOrForeignElement

Added: trunk/LayoutTests/webgpu/whlsl/matrix-alignment-expected.txt (0 => 249214)


--- trunk/LayoutTests/webgpu/whlsl/matrix-alignment-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl/matrix-alignment-expected.txt	2019-08-28 19:46:36 UTC (rev 249214)
@@ -0,0 +1,5 @@
+PASS 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Property changes on: trunk/LayoutTests/webgpu/whlsl/matrix-alignment-expected.txt
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Author Date Id Rev URL \ No newline at end of property

Added: trunk/LayoutTests/webgpu/whlsl/matrix-alignment.html (0 => 249214)


--- trunk/LayoutTests/webgpu/whlsl/matrix-alignment.html	                        (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl/matrix-alignment.html	2019-08-28 19:46:36 UTC (rev 249214)
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+const shaderSource = `
+struct Container2x2 {
+    float x;
+    float2x2 m;
+    float y;
+}
+
+struct Container2x3 {
+    float x;
+    float2x3 m;
+    float y;
+}
+
+struct Container2x4 {
+    float x;
+    float2x4 m;
+    float y;
+}
+
+struct Container3x2 {
+    float x;
+    float3x2 m;
+    float y;
+}
+
+struct Container3x3 {
+    float x;
+    float3x3 m;
+    float y;
+}
+
+struct Container3x4 {
+    float x;
+    float3x4 m;
+    float y;
+}
+
+struct Container4x2 {
+    float x;
+    float4x2 m;
+    float y;
+}
+
+struct Container4x3 {
+    float x;
+    float4x3 m;
+    float y;
+}
+
+struct Container4x4 {
+    float x;
+    float4x4 m;
+    float y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader2x2(device Container2x2[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader2x3(device Container2x3[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader2x4(device Container2x4[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader3x2(device Container3x2[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader3x3(device Container3x3[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader3x4(device Container3x4[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader4x2(device Container4x2[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader4x3(device Container4x3[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+
+[numthreads(1, 1, 1)]
+compute void computeShader4x4(device Container4x4[] input : register(u0), device float[] output : register(u1)) {
+    output[0] = input[0].m[0][0];
+    output[1] = input[0].y;
+}
+`;
+
+async function start(device) {
+    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
+
+    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}, {binding: 1, visibility: 7, type: "storage-buffer"}]};
+    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
+    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
+    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
+
+    const inputSize = Float32Array.BYTES_PER_ELEMENT * 32;
+    const outputSize = Float32Array.BYTES_PER_ELEMENT * 2;
+
+    const uploadBufferDescriptor = {size: inputSize, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
+    const uploadBuffer = device.createBuffer(uploadBufferDescriptor);
+    const uploadBufferArrayBuffer = await uploadBuffer.mapWriteAsync();
+    const uploadBufferFloat32Array = new Float32Array(uploadBufferArrayBuffer);
+    for (let i = 0; i < 32; ++i)
+        uploadBufferFloat32Array[i] = i;
+    uploadBuffer.unmap();
+
+    const inputBufferDescriptor = {size: inputSize, usage: GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.STORAGE};
+    const inputBuffer = device.createBuffer(inputBufferDescriptor);
+
+    const outputBufferDescriptor = {size: outputSize, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ};
+    const outputBuffer = device.createBuffer(outputBufferDescriptor);
+
+    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [{binding: 0, resource: {buffer: inputBuffer, size: inputSize}}, {binding: 1, resource: {buffer: outputBuffer, size: outputSize}}]};
+    const bindGroup = device.createBindGroup(bindGroupDescriptor);
+
+    let tests = ["computeShader2x2", "computeShader2x3", "computeShader2x4", "computeShader3x2", "computeShader3x3", "computeShader3x4", "computeShader4x2", "computeShader4x3", "computeShader4x4"];
+    let results = [];
+    for (let test of tests) {
+        const computePipeline = device.createComputePipeline({computeStage: {module: shaderModule, entryPoint: test}, layout: pipelineLayout});
+        const commandEncoder = device.createCommandEncoder(); // {}
+        commandEncoder.copyBufferToBuffer(uploadBuffer, 0, inputBuffer, 0, inputSize);
+        const computePassEncoder = commandEncoder.beginComputePass();
+        computePassEncoder.setPipeline(computePipeline);
+        computePassEncoder.setBindGroup(0, bindGroup);
+        computePassEncoder.dispatch(1, 1, 1);
+        computePassEncoder.endPass();
+        const commandBuffer = commandEncoder.finish();
+        device.getQueue().submit([commandBuffer]);
+
+        const outputArrayBuffer = await outputBuffer.mapReadAsync();
+        const outputFloat32Array = new Float32Array(outputArrayBuffer);
+        results.push(outputFloat32Array[0]);
+        results.push(outputFloat32Array[1]);
+        outputBuffer.unmap();
+    }
+    let expected = [2, 6, 4, 12, 4, 12, 2, 8, 4, 16, 4, 16, 2, 10, 4, 20, 4, 20];
+    let error = false;
+    for (let i = 0; i < expected.length; ++i) {
+        if (results[i] != expected[i]) {
+            testFailed("");
+            return;
+        }
+    }
+    testPassed("");
+}
+window.jsTestIsAsync = true;
+getBasicDevice().then(function(device) {
+    start(device).then(function() {
+        finishJSTest();
+    }, function(e) {
+        testFailed("");
+        finishJSTest();
+    });
+}, function() {
+    testPassed("");
+    finishJSTest();
+});
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (249213 => 249214)


--- trunk/Source/WebCore/ChangeLog	2019-08-28 19:36:23 UTC (rev 249213)
+++ trunk/Source/WebCore/ChangeLog	2019-08-28 19:46:36 UTC (rev 249214)
@@ -1,3 +1,32 @@
+2019-08-28  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [WHLSL] Matrices need to have correct alignment
+        https://bugs.webkit.org/show_bug.cgi?id=201212
+
+        Reviewed by Robin Morisset.
+
+        Matrices have particular alignment requirements and size requirements.
+
+          Type   | Alignment | Size
+        ---------------------------
+        float2x2 |         8 |   16
+        float2x3 |        16 |   32
+        float2x4 |        16 |   32
+        float3x2 |         8 |   24
+        float3x3 |        16 |   48
+        float3x4 |        16 |   48
+        float4x2 |         8 |   32
+        float4x3 |        16 |   64
+        float4x4 |        16 |   64
+
+        These are important because they may be a member of a struct, and we don't want to misplace
+        every successive item in the struct.
+
+        Test: webgpu/whlsl/matrix-alignment.html
+
+        * Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp:
+        (WebCore::WHLSL::Metal::writeNativeType):
+
 2019-08-28  Rob Buis  <rb...@igalia.com>
 
         Implement HTMLOrForeignElement

Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp (249213 => 249214)


--- trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp	2019-08-28 19:36:23 UTC (rev 249213)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp	2019-08-28 19:46:36 UTC (rev 249214)
@@ -38,6 +38,11 @@
 
 namespace Metal {
 
+enum class MatrixType : uint8_t {
+    Float,
+    Bool
+};
+
 String writeNativeType(AST::NativeTypeDeclaration& nativeTypeDeclaration)
 {
     if (nativeTypeDeclaration.name() == "void")
@@ -96,11 +101,11 @@
         auto& unifyNode = typeReference->unifyNode();
         auto& namedType = downcast<AST::NamedType>(unifyNode);
         auto& parameterType = downcast<AST::NativeTypeDeclaration>(namedType);
-        auto prefix = ([&]() -> String {
+        auto matrixType = ([&]() -> MatrixType {
             if (parameterType.name() == "bool")
-                return "bool";
+                return MatrixType::Bool;
             ASSERT(parameterType.name() == "float");
-            return "float";
+            return MatrixType::Float;
         })();
 
         ASSERT(WTF::holds_alternative<AST::ConstantExpression>(nativeTypeDeclaration.typeArguments()[1]));
@@ -114,7 +119,17 @@
         auto& integerLiteral2 = constantExpression2.integerLiteral();
         unsigned columns = integerLiteral2.value();
         ASSERT(columns == 2 || columns == 3 || columns == 4);
-        return makeString("array<", prefix, ", ", columns * rows, ">");
+
+        switch (matrixType) {
+        case MatrixType::Float: {
+            unsigned alignment = columns == 2 ? 8 : 16;
+            if (columns == 3)
+                columns = 4;
+            return makeString("array<float, ", columns * rows, "> __attribute__((aligned(", alignment, ")))");
+        }
+        case MatrixType::Bool:
+            return makeString("array<bool, ", columns * rows, ">");
+        }
     }
     ASSERT(nativeTypeDeclaration.typeArguments().size() == 1);
     ASSERT(WTF::holds_alternative<Ref<AST::TypeReference>>(nativeTypeDeclaration.typeArguments()[0]));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to