[WHLSL] Hook up common texture functions
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2019 09:40:41 +0000 (09:40 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2019 09:40:41 +0000 (09:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198704
<rdar://problem/51668841>

Reviewed by Saam Barati.

Source/WebCore:

This patch adds the Metal implementation of the Sample(), Load(), and GetDimensions()
texture functions. The implementation simply performs string concatenation to produce the
correct results, and adds many new native functions to the standard library.

We can't zero-fill texture types or sampler types, so this patch forbids default
constructors for those types. It also forbids those types to exist within arrays, array
references, or pointers, becuase an out-of-bounds access may cause us to try to zero-fill
them.

Tests: webgpu/whlsl-textures-getdimensions.html
       webgpu/whlsl-textures-load.html
       webgpu/whlsl-textures-sample.html

* Modules/webgpu/WHLSL/AST/WHLSLNativeTypeDeclaration.h: Add some more introspection functions
so we can generate the necessary Metal functions for the appropriate texture types.
(WebCore::WHLSL::AST::NativeTypeDeclaration::isAtomic const):
(WebCore::WHLSL::AST::NativeTypeDeclaration::isTextureArray const):
(WebCore::WHLSL::AST::NativeTypeDeclaration::isDepthTexture const):
(WebCore::WHLSL::AST::NativeTypeDeclaration::isWritableTexture const):
(WebCore::WHLSL::AST::NativeTypeDeclaration::textureDimension const):
(WebCore::WHLSL::AST::NativeTypeDeclaration::setIsTextureArray):
(WebCore::WHLSL::AST::NativeTypeDeclaration::setIsDepthTexture):
(WebCore::WHLSL::AST::NativeTypeDeclaration::setIsWritableTexture):
(WebCore::WHLSL::AST::NativeTypeDeclaration::setTextureDimension):
(WebCore::WHLSL::AST::NativeTypeDeclaration::isAtom const): Deleted.
* Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp: Native types can be passed into
entry points, too.
(WebCore::WHLSL::Metal::EntryPointScaffolding::resourceHelperTypes):
* Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp: Entry points that return void don't need a
semantic.
(WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
* Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp: Implement the functions.
(WebCore::WHLSL::Metal::vectorLength):
(WebCore::WHLSL::Metal::vectorInnerType):
(WebCore::WHLSL::Metal::vectorSuffix):
(WebCore::WHLSL::Metal::writeNativeFunction):
* Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp: Textures come in two flavors: sample-able
and read/write-able. Make sure we produce the correct Metal types for them.
(WebCore::WHLSL::Metal::writeNativeType):
* Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.cpp: We can't auto-initialize textures and
samplers. Therefore, this function needs to be able to fail.
(WebCore::WHLSL::AutoInitialize::visit):
(WebCore::WHLSL::autoInitializeVariables):
* Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.h:
* Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp: We can't auto-initialize textures, so users
shouldn't be able to either.
(WebCore::WHLSL::checkDuplicateFunctions):
* Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp: Added. Make sure textures and samplers can't
exist inside arrays, array references, or pointers. This is because out-of-bounds accesses may cause
us to attempt to zero-fill the inner type, but we can't zero-fill textures and samplers.
(WebCore::WHLSL::TextureReferencesChecker::TextureReferencesChecker):
(WebCore::WHLSL::Searcher::Searcher):
(WebCore::WHLSL::Searcher::found const):
(WebCore::WHLSL::Searcher::visit):
(WebCore::WHLSL::TextureReferencesChecker::containsTextureOrSampler):
(WebCore::WHLSL::TextureReferencesChecker::visit):
(WebCore::WHLSL::checkTextureReferences):
* Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.h.
* Modules/webgpu/WHLSL/WHLSLChecker.cpp:
* Modules/webgpu/WHLSL/WHLSLIntrinsics.cpp: Record more detailed information about texture types,
so we can emit correct Metal code.
(WebCore::WHLSL::Intrinsics::addFullTexture):
(WebCore::WHLSL::Intrinsics::addDepthTexture):
* Modules/webgpu/WHLSL/WHLSLIntrinsics.h:
(WebCore::WHLSL::Intrinsics::WTF_ARRAY_LENGTH):
* Modules/webgpu/WHLSL/WHLSLNameResolver.cpp: Nested NameResolvers need to propagate their error. Also,
native functions with named arguments shouldn't be adding their arguments to the global scope.
(WebCore::WHLSL::NameResolver::visit):
* Modules/webgpu/WHLSL/WHLSLNameResolver.h:
* Modules/webgpu/WHLSL/WHLSLPrepare.cpp:
(WebCore::WHLSL::prepareShared):
* Modules/webgpu/WHLSL/WHLSLProgram.h:
(WebCore::WHLSL::Program::intrinsics const):
* Modules/webgpu/WHLSL/WHLSLRecursiveTypeChecker.cpp:
* Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt: Metal doesn't have writable depth textures.
* Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp:
* Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp: Don't generate default constructors for textures
or samplers.
(WebCore::WHLSL::synthesizeConstructors):
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/gpu/GPUTexture.h: Make texture usages more clear.
(WebCore::GPUTexture::isSampled const):
(WebCore::GPUTexture::isStorage const):
* platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm: Ditto.
(WebCore::GPUBindGroup::tryCreate):
* platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm: Ditto.
(WebCore::GPUProgrammablePassEncoder::setBindGroup):
* platform/graphics/gpu/cocoa/GPUTextureMetal.mm: Ditto.
(WebCore::mtlTextureUsageForGPUTextureUsageFlags):

LayoutTests:

Make the text tests play better with js-test-pre.js.

* webgpu/whlsl-buffer-length.html:
* webgpu/whlsl-compute-expected.txt:
* webgpu/whlsl-compute.html:
* webgpu/whlsl-duplicate-types-should-not-produce-duplicate-ctors.html:
* webgpu/whlsl-null-dereference-expected.txt:
* webgpu/whlsl-null-dereference.html:
* webgpu/whlsl-oob-access-expected.txt:
* webgpu/whlsl-oob-access.html:
* webgpu/whlsl-textures-getdimensions-expected.txt: Added.
* webgpu/whlsl-textures-getdimensions.html: Copied from LayoutTests/webgpu/whlsl-buffer-length.html.
* webgpu/whlsl-textures-load-expected.html: Added.
* webgpu/whlsl-textures-load.html: Added.
* webgpu/whlsl-textures-sample-expected.html: Added.
* webgpu/whlsl-textures-sample.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246631 268f45cc-cd09-0410-ab3c-d52691b4dbfc

45 files changed:
LayoutTests/ChangeLog
LayoutTests/webgpu/whlsl-buffer-length-expected.txt
LayoutTests/webgpu/whlsl-buffer-length.html
LayoutTests/webgpu/whlsl-compute-expected.txt
LayoutTests/webgpu/whlsl-compute.html
LayoutTests/webgpu/whlsl-duplicate-types-should-not-produce-duplicate-ctors-expected.txt
LayoutTests/webgpu/whlsl-duplicate-types-should-not-produce-duplicate-ctors.html
LayoutTests/webgpu/whlsl-null-dereference-expected.txt
LayoutTests/webgpu/whlsl-null-dereference.html
LayoutTests/webgpu/whlsl-oob-access-expected.txt
LayoutTests/webgpu/whlsl-oob-access.html
LayoutTests/webgpu/whlsl-textures-getdimensions-expected.txt [new file with mode: 0644]
LayoutTests/webgpu/whlsl-textures-getdimensions.html [new file with mode: 0644]
LayoutTests/webgpu/whlsl-textures-load-expected.html [new file with mode: 0644]
LayoutTests/webgpu/whlsl-textures-load.html [new file with mode: 0644]
LayoutTests/webgpu/whlsl-textures-sample-expected.html [new file with mode: 0644]
LayoutTests/webgpu/whlsl-textures-sample.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLNativeTypeDeclaration.h
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLIntrinsics.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLIntrinsics.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLProgram.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLRecursiveTypeChecker.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt
Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp
Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/graphics/gpu/GPUTexture.h
Source/WebCore/platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm
Source/WebCore/platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm
Source/WebCore/platform/graphics/gpu/cocoa/GPUTextureMetal.mm

index f47b9f6..54305a0 100644 (file)
@@ -1,3 +1,28 @@
+2019-06-19  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WHLSL] Hook up common texture functions
+        https://bugs.webkit.org/show_bug.cgi?id=198704
+        <rdar://problem/51668841>
+
+        Reviewed by Saam Barati.
+
+        Make the text tests play better with js-test-pre.js.
+
+        * webgpu/whlsl-buffer-length.html:
+        * webgpu/whlsl-compute-expected.txt:
+        * webgpu/whlsl-compute.html:
+        * webgpu/whlsl-duplicate-types-should-not-produce-duplicate-ctors.html:
+        * webgpu/whlsl-null-dereference-expected.txt:
+        * webgpu/whlsl-null-dereference.html:
+        * webgpu/whlsl-oob-access-expected.txt:
+        * webgpu/whlsl-oob-access.html:
+        * webgpu/whlsl-textures-getdimensions-expected.txt: Added.
+        * webgpu/whlsl-textures-getdimensions.html: Copied from LayoutTests/webgpu/whlsl-buffer-length.html.
+        * webgpu/whlsl-textures-load-expected.html: Added.
+        * webgpu/whlsl-textures-load.html: Added.
+        * webgpu/whlsl-textures-sample-expected.html: Added.
+        * webgpu/whlsl-textures-sample.html: Added.
+
 2019-06-19  Rob Buis  <rbuis@igalia.com>
 
         Make preload/link-header-preload-imagesrcset.html work on DPR != 1
index c1b6704..597f203 100644 (file)
@@ -1,5 +1,5 @@
+PASS resultUint32Array[0] is 1337
 PASS successfullyParsed is true
 
 TEST COMPLETE
-PASS resultUint32Array[0] is 1337
 
index 1b1512d..ba201c4 100644 (file)
@@ -59,15 +59,12 @@ async function start() {
     shouldBe("resultUint32Array[0]", "1337");
     resultsBuffer.unmap();
 }
-if (window.testRunner)
-    testRunner.waitUntilDone();
+window.jsTestIsAsync = true;
 window.addEventListener("load", function() {
     start().then(function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     }, function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     });
 });
 </script>
index 6e1668a..a935cf8 100644 (file)
@@ -1,6 +1,3 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
 PASS resultsFloat32Array[0] is 2
 PASS resultsFloat32Array[1] is 4
 PASS resultsFloat32Array[2] is 6
@@ -9,4 +6,7 @@ PASS resultsFloat32Array[4] is 5
 PASS resultsFloat32Array[5] is 6
 PASS resultsFloat32Array[6] is 7
 PASS resultsFloat32Array[7] is 8
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index 8a68efd..8093e85 100644 (file)
@@ -73,15 +73,12 @@ async function start() {
     shouldBe("resultsFloat32Array[7]", "8");
     resultsBuffer.unmap();
 }
-if (window.testRunner)
-    testRunner.waitUntilDone();
+window.jsTestIsAsync = true;
 window.addEventListener("load", function() {
     start().then(function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     }, function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     });
 });
 </script>
index 6e1668a..a935cf8 100644 (file)
@@ -1,6 +1,3 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
 PASS resultsFloat32Array[0] is 2
 PASS resultsFloat32Array[1] is 4
 PASS resultsFloat32Array[2] is 6
@@ -9,4 +6,7 @@ PASS resultsFloat32Array[4] is 5
 PASS resultsFloat32Array[5] is 6
 PASS resultsFloat32Array[6] is 7
 PASS resultsFloat32Array[7] is 8
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index 578ea7e..0ea596c 100644 (file)
@@ -94,15 +94,12 @@ async function start() {
     shouldBe("resultsFloat32Array[7]", "8");
     resultsBuffer.unmap();
 }
-if (window.testRunner)
-    testRunner.waitUntilDone();
+window.jsTestIsAsync = true;
 window.addEventListener("load", function() {
     start().then(function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     }, function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     });
 });
 </script>
index 6e1668a..a935cf8 100644 (file)
@@ -1,6 +1,3 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
 PASS resultsFloat32Array[0] is 2
 PASS resultsFloat32Array[1] is 4
 PASS resultsFloat32Array[2] is 6
@@ -9,4 +6,7 @@ PASS resultsFloat32Array[4] is 5
 PASS resultsFloat32Array[5] is 6
 PASS resultsFloat32Array[6] is 7
 PASS resultsFloat32Array[7] is 8
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index a848867..d692457 100644 (file)
@@ -109,15 +109,12 @@ async function start() {
     shouldBe("resultsFloat32Array[7]", "8");
     resultsBuffer.unmap();
 }
-if (window.testRunner)
-    testRunner.waitUntilDone();
+window.jsTestIsAsync = true;
 window.addEventListener("load", function() {
     start().then(function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     }, function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     });
 });
 </script>
index 6e1668a..a935cf8 100644 (file)
@@ -1,6 +1,3 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
 PASS resultsFloat32Array[0] is 2
 PASS resultsFloat32Array[1] is 4
 PASS resultsFloat32Array[2] is 6
@@ -9,4 +6,7 @@ PASS resultsFloat32Array[4] is 5
 PASS resultsFloat32Array[5] is 6
 PASS resultsFloat32Array[6] is 7
 PASS resultsFloat32Array[7] is 8
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index 8c696f2..31760d7 100644 (file)
@@ -76,15 +76,12 @@ async function start() {
     shouldBe("resultsFloat32Array[7]", "8");
     resultsBuffer.unmap();
 }
-if (window.testRunner)
-    testRunner.waitUntilDone();
+window.jsTestIsAsync = true;
 window.addEventListener("load", function() {
     start().then(function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     }, function() {
-        if (window.testRunner)
-            testRunner.notifyDone();
+        finishJSTest();
     });
 });
 </script>
diff --git a/LayoutTests/webgpu/whlsl-textures-getdimensions-expected.txt b/LayoutTests/webgpu/whlsl-textures-getdimensions-expected.txt
new file mode 100644 (file)
index 0000000..794166f
--- /dev/null
@@ -0,0 +1,7 @@
+PASS resultsUint32Array[0] is 2
+PASS resultsUint32Array[1] is 2
+PASS resultsUint32Array[2] is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/webgpu/whlsl-textures-getdimensions.html b/LayoutTests/webgpu/whlsl-textures-getdimensions.html
new file mode 100644 (file)
index 0000000..1a80f7e
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+const shaderSource = `
+[numthreads(1, 1, 1)]
+compute void computeShader(Texture2D<float4> theTexture : register(t0), device uint[] theBuffer : register(u1)) {
+    uint width;
+    uint height;
+    uint numberOfLevels;
+    GetDimensions(theTexture, 0, &width, &height, &numberOfLevels);
+    theBuffer[0] = width;
+    theBuffer[1] = height;
+    theBuffer[2] = numberOfLevels;
+}
+`;
+let resultsUint32Array;
+async function start() {
+    const adapter = await navigator.gpu.requestAdapter();
+    const device = await adapter.requestDevice();
+
+    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
+    const computeStage = {module: shaderModule, entryPoint: "computeShader"};
+
+    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "sampled-texture"}, {binding: 1, visibility: 7, type: "storage-buffer"}]};
+    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
+    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
+    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
+
+    const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
+    const computePipeline = device.createComputePipeline(computePipelineDescriptor);
+
+    const textureDescriptor = {size: {width: 2, height: 2, depth: 1}, format: "rgba8unorm", usage: GPUTextureUsage.SAMPLED};
+    const texture = device.createTexture(textureDescriptor);
+    const textureView = texture.createDefaultView();
+
+    const resultsBufferDescriptor = {size: Uint32Array.BYTES_PER_ELEMENT * 3, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ};
+    const resultsBuffer = device.createBuffer(resultsBufferDescriptor);
+
+    const bufferBinding = {buffer: resultsBuffer, size: Uint32Array.BYTES_PER_ELEMENT * 3};
+    const bindGroupBindings = [{binding: 0, resource: textureView}, {binding: 1, resource: bufferBinding}];
+    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: bindGroupBindings};
+    const bindGroup = device.createBindGroup(bindGroupDescriptor);
+
+    const commandEncoder = device.createCommandEncoder(); // {}
+    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 resultsArrayBuffer = await resultsBuffer.mapReadAsync();
+    resultsUint32Array = new Uint32Array(resultsArrayBuffer);
+    shouldBe("resultsUint32Array[0]", "2");
+    shouldBe("resultsUint32Array[1]", "2");
+    shouldBe("resultsUint32Array[2]", "1");
+    resultsBuffer.unmap();
+}
+window.jsTestIsAsync = true;
+window.addEventListener("load", function() {
+    start().then(function() {
+        finishJSTest();
+    }, function(e) {
+        finishJSTest();
+    });
+});
+</script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/webgpu/whlsl-textures-load-expected.html b/LayoutTests/webgpu/whlsl-textures-load-expected.html
new file mode 100644 (file)
index 0000000..f417050
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<canvas id="canvas" width="400" height="400"></canvas>
+<script>
+async function start() {
+    const canvas = document.getElementById("canvas");
+    const context = canvas.getContext("2d");
+    context.fillStyle = "blue";
+    context.fillRect(0, 0, 400, 400);
+    context.fillStyle = "white";
+    context.fillRect(100, 100, 200, 200);
+}
+window.addEventListener("load", start);
+</script>
+</body>
+</html>
diff --git a/LayoutTests/webgpu/whlsl-textures-load.html b/LayoutTests/webgpu/whlsl-textures-load.html
new file mode 100644 (file)
index 0000000..edcd4e2
--- /dev/null
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<canvas id="canvas" width="400" height="400"></canvas>
+<script>
+const shaderSource = `
+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position {
+    return position;
+}
+
+fragment float4 fragmentShader(Texture2D<float4> theTexture : register(t0)) : SV_Target 0 {
+    return Load(theTexture, int2(0, 0));
+}
+`;
+async function start() {
+    const adapter = await navigator.gpu.requestAdapter();
+    const device = await adapter.requestDevice();
+
+    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
+    const vertexStage = {module: shaderModule, entryPoint: "vertexShader"};
+    const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"};
+    const primitiveTopology = "triangle-strip";
+    const rasterizationState = {frontFace: "cw", cullMode: "none"};
+    const alphaBlend = {};
+    const colorBlend = {};
+    const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL
+    const depthStencilState = null;
+    
+    const attribute0 = {shaderLocation: 0, format: "float4"};
+    const input0 = {stride: 16, attributeSet: [attribute0]};
+    const inputs = [input0];
+    const vertexInput = {vertexBuffers: inputs};
+
+    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "sampled-texture"}]};
+    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
+    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
+    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
+
+    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
+    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
+
+    const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE};
+    const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor);
+    const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync();
+    const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer);
+    vertexBuffer0Float32Array[0] = -0.5;
+    vertexBuffer0Float32Array[1] = -0.5;
+    vertexBuffer0Float32Array[2] = 1.0;
+    vertexBuffer0Float32Array[3] = 1;
+    vertexBuffer0Float32Array[4] = -0.5;
+    vertexBuffer0Float32Array[5] = 0.5;
+    vertexBuffer0Float32Array[6] = 1.0;
+    vertexBuffer0Float32Array[7] = 1;
+    vertexBuffer0Float32Array[8] = 0.5;
+    vertexBuffer0Float32Array[9] = -0.5;
+    vertexBuffer0Float32Array[10] = 1.0;
+    vertexBuffer0Float32Array[11] = 1;
+    vertexBuffer0Float32Array[12] = 0.5;
+    vertexBuffer0Float32Array[13] = 0.5;
+    vertexBuffer0Float32Array[14] = 1.0;
+    vertexBuffer0Float32Array[15] = 1;
+    vertexBuffer0.unmap();
+
+    const textureDataBufferDescriptor = {size: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2, usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.MAP_WRITE};
+    const textureDataBuffer = device.createBuffer(textureDataBufferDescriptor);
+    const textureDataBufferArrayBuffer = await textureDataBuffer.mapWriteAsync();
+    const textureDataBufferUint8Array = new Uint8Array(textureDataBufferArrayBuffer);
+    textureDataBufferUint8Array[0] = 255;
+    textureDataBufferUint8Array[1] = 255;
+    textureDataBufferUint8Array[2] = 255;
+    textureDataBufferUint8Array[3] = 255;
+    textureDataBufferUint8Array[4] = 128;
+    textureDataBufferUint8Array[5] = 128;
+    textureDataBufferUint8Array[6] = 128;
+    textureDataBufferUint8Array[7] = 255;
+    textureDataBufferUint8Array[8] = 128;
+    textureDataBufferUint8Array[9] = 128;
+    textureDataBufferUint8Array[10] = 128;
+    textureDataBufferUint8Array[11] = 255;
+    textureDataBufferUint8Array[12] = 128;
+    textureDataBufferUint8Array[13] = 128;
+    textureDataBufferUint8Array[14] = 128;
+    textureDataBufferUint8Array[15] = 255;
+    textureDataBuffer.unmap();
+
+    const textureDescriptor = {size: {width: 2, height: 2, depth: 1}, format: "rgba8unorm", usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.TRANSFER_DST};
+    const texture = device.createTexture(textureDescriptor);
+    const textureView = texture.createDefaultView();
+
+    const bindGroupBindings = [{binding: 0, resource: textureView}];
+    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: bindGroupBindings};
+    const bindGroup = device.createBindGroup(bindGroupDescriptor);
+
+    const canvas = document.getElementById("canvas");
+    const context = canvas.getContext("gpu");
+    const swapChainDescriptor = {device, format: "bgra8unorm"};
+    const swapChain = context.configureSwapChain(swapChainDescriptor);
+    const outputTexture = swapChain.getCurrentTexture();
+    const outputTextureView = outputTexture.createDefaultView();
+
+    const commandEncoder = device.createCommandEncoder(); // {}
+
+    const bufferCopyView = {buffer: textureDataBuffer, rowPitch: Uint8Array.BYTES_PER_ELEMENT * 4 * 2, imageHeight: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2};
+    const textureCopyView = {texture: texture};
+    const copySize = {width: 2, height: 2, depth: 1};
+    commandEncoder.copyBufferToTexture(bufferCopyView, textureCopyView, copySize);
+
+    const clearColor = {r: 0, g: 0, b: 1, a: 1};
+    const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor}];
+    const depthStencilAttachment = null;
+    const renderPassDescriptor = {colorAttachments, depthStencilAttachment};
+    const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+    renderPassEncoder.setPipeline(renderPipeline);
+    renderPassEncoder.setBindGroup(0, bindGroup);
+    renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]);
+    renderPassEncoder.draw(4, 1, 0, 0);
+    renderPassEncoder.endPass();
+    const commandBuffer = commandEncoder.finish();
+    device.getQueue().submit([commandBuffer]);
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+if (window.testRunner)
+    testRunner.waitUntilDone();
+window.addEventListener("load", start);
+</script>
+</body>
+</html>
diff --git a/LayoutTests/webgpu/whlsl-textures-sample-expected.html b/LayoutTests/webgpu/whlsl-textures-sample-expected.html
new file mode 100644 (file)
index 0000000..f417050
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<canvas id="canvas" width="400" height="400"></canvas>
+<script>
+async function start() {
+    const canvas = document.getElementById("canvas");
+    const context = canvas.getContext("2d");
+    context.fillStyle = "blue";
+    context.fillRect(0, 0, 400, 400);
+    context.fillStyle = "white";
+    context.fillRect(100, 100, 200, 200);
+}
+window.addEventListener("load", start);
+</script>
+</body>
+</html>
diff --git a/LayoutTests/webgpu/whlsl-textures-sample.html b/LayoutTests/webgpu/whlsl-textures-sample.html
new file mode 100644 (file)
index 0000000..2dffb00
--- /dev/null
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<canvas id="canvas" width="400" height="400"></canvas>
+<script>
+const shaderSource = `
+vertex float4 vertexShader(float4 position : attribute(0)) : SV_Position {
+    return position;
+}
+
+fragment float4 fragmentShader(Texture2D<float4> theTexture : register(t0), sampler theSampler : register(s1)) : SV_Target 0 {
+    return Sample(theTexture, theSampler, float2(0.5, 0.5));
+}
+`;
+async function start() {
+    const adapter = await navigator.gpu.requestAdapter();
+    const device = await adapter.requestDevice();
+
+    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
+    const vertexStage = {module: shaderModule, entryPoint: "vertexShader"};
+    const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"};
+    const primitiveTopology = "triangle-strip";
+    const rasterizationState = {frontFace: "cw", cullMode: "none"};
+    const alphaBlend = {};
+    const colorBlend = {};
+    const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL
+    const depthStencilState = null;
+    
+    const attribute0 = {shaderLocation: 0, format: "float4"};
+    const input0 = {stride: 16, attributeSet: [attribute0]};
+    const inputs = [input0];
+    const vertexInput = {vertexBuffers: inputs};
+
+    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "sampled-texture"}, {binding: 1, visibility: 7, type: "sampler"}]};
+    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
+    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
+    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
+
+    const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
+    const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
+
+    const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE};
+    const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor);
+    const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync();
+    const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer);
+    vertexBuffer0Float32Array[0] = -0.5;
+    vertexBuffer0Float32Array[1] = -0.5;
+    vertexBuffer0Float32Array[2] = 1.0;
+    vertexBuffer0Float32Array[3] = 1;
+    vertexBuffer0Float32Array[4] = -0.5;
+    vertexBuffer0Float32Array[5] = 0.5;
+    vertexBuffer0Float32Array[6] = 1.0;
+    vertexBuffer0Float32Array[7] = 1;
+    vertexBuffer0Float32Array[8] = 0.5;
+    vertexBuffer0Float32Array[9] = -0.5;
+    vertexBuffer0Float32Array[10] = 1.0;
+    vertexBuffer0Float32Array[11] = 1;
+    vertexBuffer0Float32Array[12] = 0.5;
+    vertexBuffer0Float32Array[13] = 0.5;
+    vertexBuffer0Float32Array[14] = 1.0;
+    vertexBuffer0Float32Array[15] = 1;
+    vertexBuffer0.unmap();
+
+    const textureDataBufferDescriptor = {size: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2, usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.MAP_WRITE};
+    const textureDataBuffer = device.createBuffer(textureDataBufferDescriptor);
+    const textureDataBufferArrayBuffer = await textureDataBuffer.mapWriteAsync();
+    const textureDataBufferUint8Array = new Uint8Array(textureDataBufferArrayBuffer);
+    textureDataBufferUint8Array[0] = 255;
+    textureDataBufferUint8Array[1] = 255;
+    textureDataBufferUint8Array[2] = 255;
+    textureDataBufferUint8Array[3] = 255;
+    textureDataBufferUint8Array[4] = 255;
+    textureDataBufferUint8Array[5] = 255;
+    textureDataBufferUint8Array[6] = 255;
+    textureDataBufferUint8Array[7] = 255;
+    textureDataBufferUint8Array[8] = 255;
+    textureDataBufferUint8Array[9] = 255;
+    textureDataBufferUint8Array[10] = 255;
+    textureDataBufferUint8Array[11] = 255;
+    textureDataBufferUint8Array[12] = 255;
+    textureDataBufferUint8Array[13] = 255;
+    textureDataBufferUint8Array[14] = 255;
+    textureDataBufferUint8Array[15] = 255;
+    textureDataBuffer.unmap();
+
+    const textureDescriptor = {size: {width: 2, height: 2, depth: 1}, format: "rgba8unorm", usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.TRANSFER_DST};
+    const texture = device.createTexture(textureDescriptor);
+    const textureView = texture.createDefaultView();
+
+    const samplerDescriptor = {magFilter: "linear", minFilter: "linear"};
+    const sampler = device.createSampler(samplerDescriptor);
+
+    const bindGroupBindings = [{binding: 0, resource: textureView}, {binding: 1, resource: sampler}];
+    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: bindGroupBindings};
+    const bindGroup = device.createBindGroup(bindGroupDescriptor);
+
+    const canvas = document.getElementById("canvas");
+    const context = canvas.getContext("gpu");
+    const swapChainDescriptor = {device, format: "bgra8unorm"};
+    const swapChain = context.configureSwapChain(swapChainDescriptor);
+    const outputTexture = swapChain.getCurrentTexture();
+    const outputTextureView = outputTexture.createDefaultView();
+
+    const commandEncoder = device.createCommandEncoder(); // {}
+
+    const bufferCopyView = {buffer: textureDataBuffer, rowPitch: Uint8Array.BYTES_PER_ELEMENT * 4 * 2, imageHeight: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2};
+    const textureCopyView = {texture: texture};
+    const copySize = {width: 2, height: 2, depth: 1};
+    commandEncoder.copyBufferToTexture(bufferCopyView, textureCopyView, copySize);
+
+    const clearColor = {r: 0, g: 0, b: 1, a: 1};
+    const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor}];
+    const depthStencilAttachment = null;
+    const renderPassDescriptor = {colorAttachments, depthStencilAttachment};
+    const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
+    renderPassEncoder.setPipeline(renderPipeline);
+    renderPassEncoder.setBindGroup(0, bindGroup);
+    renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]);
+    renderPassEncoder.draw(4, 1, 0, 0);
+    renderPassEncoder.endPass();
+    const commandBuffer = commandEncoder.finish();
+    device.getQueue().submit([commandBuffer]);
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+if (window.testRunner)
+    testRunner.waitUntilDone();
+window.addEventListener("load", start);
+</script>
+</body>
+</html>
index 96f4f2a..36e14cd 100644 (file)
@@ -1,3 +1,102 @@
+2019-06-19  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WHLSL] Hook up common texture functions
+        https://bugs.webkit.org/show_bug.cgi?id=198704
+        <rdar://problem/51668841>
+
+        Reviewed by Saam Barati.
+
+        This patch adds the Metal implementation of the Sample(), Load(), and GetDimensions()
+        texture functions. The implementation simply performs string concatenation to produce the 
+        correct results, and adds many new native functions to the standard library.
+
+        We can't zero-fill texture types or sampler types, so this patch forbids default
+        constructors for those types. It also forbids those types to exist within arrays, array
+        references, or pointers, becuase an out-of-bounds access may cause us to try to zero-fill
+        them.
+
+        Tests: webgpu/whlsl-textures-getdimensions.html
+               webgpu/whlsl-textures-load.html
+               webgpu/whlsl-textures-sample.html
+
+        * Modules/webgpu/WHLSL/AST/WHLSLNativeTypeDeclaration.h: Add some more introspection functions
+        so we can generate the necessary Metal functions for the appropriate texture types.
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::isAtomic const):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::isTextureArray const):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::isDepthTexture const):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::isWritableTexture const):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::textureDimension const):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::setIsTextureArray):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::setIsDepthTexture):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::setIsWritableTexture):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::setTextureDimension):
+        (WebCore::WHLSL::AST::NativeTypeDeclaration::isAtom const): Deleted.
+        * Modules/webgpu/WHLSL/Metal/WHLSLEntryPointScaffolding.cpp: Native types can be passed into 
+        entry points, too.
+        (WebCore::WHLSL::Metal::EntryPointScaffolding::resourceHelperTypes):
+        * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp: Entry points that return void don't need a
+        semantic.
+        (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit):
+        * Modules/webgpu/WHLSL/Metal/WHLSLNativeFunctionWriter.cpp: Implement the functions.
+        (WebCore::WHLSL::Metal::vectorLength):
+        (WebCore::WHLSL::Metal::vectorInnerType):
+        (WebCore::WHLSL::Metal::vectorSuffix):
+        (WebCore::WHLSL::Metal::writeNativeFunction):
+        * Modules/webgpu/WHLSL/Metal/WHLSLNativeTypeWriter.cpp: Textures come in two flavors: sample-able
+        and read/write-able. Make sure we produce the correct Metal types for them.
+        (WebCore::WHLSL::Metal::writeNativeType):
+        * Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.cpp: We can't auto-initialize textures and 
+        samplers. Therefore, this function needs to be able to fail.
+        (WebCore::WHLSL::AutoInitialize::visit):
+        (WebCore::WHLSL::autoInitializeVariables):
+        * Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.h:
+        * Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp: We can't auto-initialize textures, so users
+        shouldn't be able to either.
+        (WebCore::WHLSL::checkDuplicateFunctions):
+        * Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp: Added. Make sure textures and samplers can't
+        exist inside arrays, array references, or pointers. This is because out-of-bounds accesses may cause
+        us to attempt to zero-fill the inner type, but we can't zero-fill textures and samplers.
+        (WebCore::WHLSL::TextureReferencesChecker::TextureReferencesChecker):
+        (WebCore::WHLSL::Searcher::Searcher):
+        (WebCore::WHLSL::Searcher::found const):
+        (WebCore::WHLSL::Searcher::visit):
+        (WebCore::WHLSL::TextureReferencesChecker::containsTextureOrSampler):
+        (WebCore::WHLSL::TextureReferencesChecker::visit):
+        (WebCore::WHLSL::checkTextureReferences):
+        * Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.h: Copied from Source/WebCore/Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.h.
+        * Modules/webgpu/WHLSL/WHLSLChecker.cpp:
+        * Modules/webgpu/WHLSL/WHLSLIntrinsics.cpp: Record more detailed information about texture types,
+        so we can emit correct Metal code.
+        (WebCore::WHLSL::Intrinsics::addFullTexture):
+        (WebCore::WHLSL::Intrinsics::addDepthTexture):
+        * Modules/webgpu/WHLSL/WHLSLIntrinsics.h:
+        (WebCore::WHLSL::Intrinsics::WTF_ARRAY_LENGTH):
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.cpp: Nested NameResolvers need to propagate their error. Also,
+        native functions with named arguments shouldn't be adding their arguments to the global scope.
+        (WebCore::WHLSL::NameResolver::visit):
+        * Modules/webgpu/WHLSL/WHLSLNameResolver.h:
+        * Modules/webgpu/WHLSL/WHLSLPrepare.cpp:
+        (WebCore::WHLSL::prepareShared):
+        * Modules/webgpu/WHLSL/WHLSLProgram.h:
+        (WebCore::WHLSL::Program::intrinsics const):
+        * Modules/webgpu/WHLSL/WHLSLRecursiveTypeChecker.cpp:
+        * Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt: Metal doesn't have writable depth textures.
+        * Modules/webgpu/WHLSL/WHLSLSynthesizeArrayOperatorLength.cpp:
+        * Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp: Don't generate default constructors for textures
+        or samplers.
+        (WebCore::WHLSL::synthesizeConstructors):
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/gpu/GPUTexture.h: Make texture usages more clear.
+        (WebCore::GPUTexture::isSampled const):
+        (WebCore::GPUTexture::isStorage const):
+        * platform/graphics/gpu/cocoa/GPUBindGroupMetal.mm: Ditto.
+        (WebCore::GPUBindGroup::tryCreate):
+        * platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm: Ditto.
+        (WebCore::GPUProgrammablePassEncoder::setBindGroup):
+        * platform/graphics/gpu/cocoa/GPUTextureMetal.mm: Ditto.
+        (WebCore::mtlTextureUsageForGPUTextureUsageFlags):
+
 2019-06-19  Justin Fan  <justin_fan@apple.com>
 
         [WHLSL] Create a shading language test harness
index fbd4ffb..72e0204 100644 (file)
@@ -59,10 +59,15 @@ public:
     bool isInt() const { return m_isInt; }
     bool isNumber() const { return m_isNumber; }
     bool isFloating() const { return m_isFloating; }
-    bool isAtom() const { return m_isAtomic; }
+    bool isAtomic() const { return m_isAtomic; }
     bool isVector() const { return m_isVector; }
     bool isMatrix() const { return m_isMatrix; }
+    bool isOpaqueType() const { return m_isOpaqueType; }
     bool isTexture() const { return m_isTexture; }
+    bool isTextureArray() const { return m_isTextureArray; }
+    bool isDepthTexture() const { return m_isDepthTexture; }
+    bool isWritableTexture() const { return m_isWritableTexture; }
+    uint textureDimension() const { return m_textureDimension; }
     bool isSigned() const { return m_isSigned; }
     const std::function<bool(int)>& canRepresentInteger() const { return m_canRepresentInteger; }
     const std::function<bool(unsigned)>& canRepresentUnsignedInteger() const { return m_canRepresentUnsignedInteger; }
@@ -78,7 +83,12 @@ public:
     void setIsAtomic() { m_isAtomic = true; }
     void setIsVector() { m_isVector = true; }
     void setIsMatrix() { m_isMatrix = true; }
+    void setIsOpaqueType() { m_isOpaqueType = true; }
     void setIsTexture() { m_isTexture = true; }
+    void setIsTextureArray() { m_isTextureArray = true; }
+    void setIsDepthTexture() { m_isDepthTexture = true; }
+    void setIsWritableTexture() { m_isWritableTexture = true; }
+    void setTextureDimension(uint textureDimension) { m_textureDimension = textureDimension; }
     void setIsSigned() { m_isSigned = true; }
     void setCanRepresentInteger(std::function<bool(int)>&& canRepresent) { m_canRepresentInteger = WTFMove(canRepresent); }
     void setCanRepresentUnsignedInteger(std::function<bool(unsigned)>&& canRepresent) { m_canRepresentUnsignedInteger = WTFMove(canRepresent); }
@@ -97,13 +107,18 @@ private:
     std::function<int64_t(int)> m_formatValueFromInteger;
     std::function<int64_t(unsigned)> m_formatValueFromUnsignedInteger;
     std::function<void(const std::function<bool(int64_t)>&)> m_iterateAllValues;
+    uint m_textureDimension { 0 };
     bool m_isInt { false };
     bool m_isNumber { false };
     bool m_isFloating { false };
     bool m_isAtomic { false };
     bool m_isVector { false };
     bool m_isMatrix { false };
+    bool m_isOpaqueType { false };
     bool m_isTexture { false };
+    bool m_isTextureArray { false };
+    bool m_isDepthTexture { false };
+    bool m_isWritableTexture { false };
     bool m_isSigned { false };
 };
 
index f4be333..1a392d5 100644 (file)
@@ -149,15 +149,23 @@ String EntryPointScaffolding::resourceHelperTypes()
             auto iterator = m_resourceMap.find(&m_layout[i].bindings[j]);
             if (iterator == m_resourceMap.end())
                 continue;
-            auto& unnamedType = *m_entryPointItems.inputs[iterator->value].unnamedType;
-            auto& referenceType = downcast<AST::ReferenceType>(unnamedType);
-            auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType());
-            auto addressSpace = toString(referenceType.addressSpace());
-            auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
-            auto index = m_namedBindGroups[i].namedBindings[j].index;
-            structItems.append(std::make_pair(index, makeString("    ", addressSpace, " ", mangledTypeName, "* ", elementName, " [[id(", index, ")]];\n")));
-            if (auto lengthInformation = m_namedBindGroups[i].namedBindings[j].lengthInformation)
-                structItems.append(std::make_pair(lengthInformation->index, makeString("uint2 ", lengthInformation->elementName, " [[id(", lengthInformation->index, ")]];")));
+            auto& type = m_entryPointItems.inputs[iterator->value].unnamedType->unifyNode();
+            if (is<AST::UnnamedType>(type) && is<AST::ReferenceType>(downcast<AST::UnnamedType>(type))) {
+                auto& referenceType = downcast<AST::ReferenceType>(downcast<AST::UnnamedType>(type));
+                auto mangledTypeName = m_typeNamer.mangledNameForType(referenceType.elementType());
+                auto addressSpace = toString(referenceType.addressSpace());
+                auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
+                auto index = m_namedBindGroups[i].namedBindings[j].index;
+                structItems.append(std::make_pair(index, makeString(addressSpace, " ", mangledTypeName, "* ", elementName, " [[id(", index, ")]];")));
+                if (auto lengthInformation = m_namedBindGroups[i].namedBindings[j].lengthInformation)
+                    structItems.append(std::make_pair(lengthInformation->index, makeString("uint2 ", lengthInformation->elementName, " [[id(", lengthInformation->index, ")]];")));
+            } else if (is<AST::NamedType>(type) && is<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(type))) {
+                auto& namedType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(type));
+                auto mangledTypeName = m_typeNamer.mangledNameForType(namedType);
+                auto elementName = m_namedBindGroups[i].namedBindings[j].elementName;
+                auto index = m_namedBindGroups[i].namedBindings[j].index;
+                structItems.append(std::make_pair(index, makeString(mangledTypeName, ' ', elementName, " [[id(", index, ")]];")));
+            }
         }
         std::sort(structItems.begin(), structItems.end(), [](const std::pair<unsigned, String>& left, const std::pair<unsigned, String>& right) {
             return left.first < right.first;
index 60cd4c0..e4f801e 100644 (file)
@@ -558,7 +558,9 @@ void FunctionDefinitionWriter::visit(AST::CallExpression& callExpression)
     auto iterator = m_functionMapping.find(callExpression.function());
     ASSERT(iterator != m_functionMapping.end());
     auto variableName = generateNextVariableName();
-    m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(callExpression.resolvedType()), ' ', variableName, " = ", iterator->value, '('));
+    if (!matches(callExpression.resolvedType(), m_intrinsics.voidType()))
+        m_stringBuilder.append(makeString(m_typeNamer.mangledNameForType(callExpression.resolvedType()), ' ', variableName, " = "));
+    m_stringBuilder.append(makeString(iterator->value, '('));
     for (size_t i = 0; i < argumentNames.size(); ++i) {
         if (i)
             m_stringBuilder.append(", ");
index 1f3d3cd..6008274 100644 (file)
@@ -81,6 +81,42 @@ static String atomicName(String input)
         return "fetch_xor"_str;
 }
 
+static int vectorLength(AST::NativeTypeDeclaration& nativeTypeDeclaration)
+{
+    int vectorLength = 1;
+    if (!nativeTypeDeclaration.typeArguments().isEmpty()) {
+        ASSERT(nativeTypeDeclaration.typeArguments().size() == 2);
+        ASSERT(WTF::holds_alternative<AST::ConstantExpression>(nativeTypeDeclaration.typeArguments()[1]));
+        vectorLength = WTF::get<AST::ConstantExpression>(nativeTypeDeclaration.typeArguments()[1]).integerLiteral().value();
+    }
+    return vectorLength;
+}
+
+static AST::NamedType& vectorInnerType(AST::NativeTypeDeclaration& nativeTypeDeclaration)
+{
+    if (nativeTypeDeclaration.typeArguments().isEmpty())
+        return nativeTypeDeclaration;
+
+    ASSERT(nativeTypeDeclaration.typeArguments().size() == 2);
+    ASSERT(WTF::holds_alternative<UniqueRef<AST::TypeReference>>(nativeTypeDeclaration.typeArguments()[0]));
+    return WTF::get<UniqueRef<AST::TypeReference>>(nativeTypeDeclaration.typeArguments()[0])->resolvedType();
+}
+
+static const char* vectorSuffix(int vectorLength)
+{
+    switch (vectorLength) {
+    case 1:
+        return "";
+    case 2:
+        return "2";
+    case 3:
+        return "3";
+    default:
+        ASSERT(vectorLength == 4);
+        return "4";
+    }
+}
+
 String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclaration, String& outputFunctionName, Intrinsics& intrinsics, TypeNamer& typeNamer, const char* memsetZeroFunctionName)
 {
     StringBuilder stringBuilder;
@@ -102,7 +138,7 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara
             auto& parameterNamedType = downcast<AST::NamedType>(parameterType);
             if (is<AST::NativeTypeDeclaration>(parameterNamedType)) {
                 auto& parameterNativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(parameterNamedType);
-                if (parameterNativeTypeDeclaration.isAtom()) {
+                if (parameterNativeTypeDeclaration.isAtomic()) {
                     stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameterName, " x) {\n"));
                     stringBuilder.append("    return atomic_load_explicit(&x, memory_order_relaxed);\n");
                     stringBuilder.append("}\n");
@@ -389,18 +425,160 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara
     }
 
     if (nativeFunctionDeclaration.name() == "Sample") {
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195813 Implement this
-        notImplemented();
+        ASSERT(nativeFunctionDeclaration.parameters().size() == 3 || nativeFunctionDeclaration.parameters().size() == 4);
+        
+        auto& textureType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[0]->type()->unifyNode()));
+        auto& locationType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[2]->type()->unifyNode()));
+        auto locationVectorLength = vectorLength(locationType);
+        auto& returnType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.type().unifyNode()));
+        auto returnVectorLength = vectorLength(returnType);
+
+        auto metalParameter1Name = typeNamer.mangledNameForType(textureType);
+        auto metalParameter2Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[1]->type());
+        auto metalParameter3Name = typeNamer.mangledNameForType(locationType);
+        String metalParameter4Name;
+        if (nativeFunctionDeclaration.parameters().size() == 4)
+            metalParameter4Name = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[3]->type());
+        auto metalReturnName = typeNamer.mangledNameForType(returnType);
+        stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " theTexture, ", metalParameter2Name, " theSampler, ", metalParameter3Name, " location"));
+        if (!metalParameter4Name.isNull())
+            stringBuilder.append(makeString(", ", metalParameter4Name, " offset"));
+        stringBuilder.append(") {\n");
+        stringBuilder.append("    return theTexture.sample(theSampler, ");
+        if (textureType.isTextureArray()) {
+            ASSERT(locationVectorLength > 1);
+            stringBuilder.append(makeString("location.", "xyzw"_str.substring(0, locationVectorLength - 1), ", location.", "xyzw"_str.substring(locationVectorLength - 1, 1)));
+        } else
+            stringBuilder.append("location");
+        if (!metalParameter4Name.isNull())
+            stringBuilder.append(", offset");
+        stringBuilder.append(")");
+        if (!textureType.isDepthTexture())
+            stringBuilder.append(makeString(".", "xyzw"_str.substring(0, returnVectorLength)));
+        stringBuilder.append(";\n");
+        stringBuilder.append("}\n");
+        return stringBuilder.toString();
     }
 
     if (nativeFunctionDeclaration.name() == "Load") {
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195813 Implement this
-        notImplemented();
+        ASSERT(nativeFunctionDeclaration.parameters().size() == 2);
+        
+        auto& textureType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[0]->type()->unifyNode()));
+        auto& locationType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[1]->type()->unifyNode()));
+        auto locationVectorLength = vectorLength(locationType);
+        auto& returnType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.type().unifyNode()));
+        auto returnVectorLength = vectorLength(returnType);
+
+        auto metalParameter1Name = typeNamer.mangledNameForType(textureType);
+        auto metalParameter2Name = typeNamer.mangledNameForType(locationType);
+        auto metalReturnName = typeNamer.mangledNameForType(returnType);
+        stringBuilder.append(makeString(metalReturnName, ' ', outputFunctionName, '(', metalParameter1Name, " theTexture, ", metalParameter2Name, " location) {\n"));
+        if (textureType.isTextureArray()) {
+            ASSERT(locationVectorLength > 1);
+            String dimensions[] = { "width"_str, "height"_str, "depth"_str };
+            for (int i = 0; i < locationVectorLength - 1; ++i) {
+                auto suffix = "xyzw"_str.substring(i, 1);
+                stringBuilder.append(makeString("    if (location.", suffix, " < 0 || static_cast<uint32_t>(location.", suffix, ") >= theTexture.get_", dimensions[i], "()) return ", metalReturnName, "(0);\n"));
+            }
+            auto suffix = "xyzw"_str.substring(locationVectorLength - 1, 1);
+            stringBuilder.append(makeString("    if (location.", suffix, " < 0 || static_cast<uint32_t>(location.", suffix, ") >= theTexture.get_array_size()) return ", metalReturnName, "(0);\n"));
+        } else {
+            if (locationVectorLength == 1)
+                stringBuilder.append(makeString("    if (location < 0 || static_cast<uint32_t>(location) >= theTexture.get_width()) return ", metalReturnName, "(0);\n"));
+            else {
+                stringBuilder.append(makeString("    if (location.x < 0 || static_cast<uint32_t>(location.x) >= theTexture.get_width()) return ", metalReturnName, "(0);\n"));
+                stringBuilder.append(makeString("    if (location.y < 0 || static_cast<uint32_t>(location.y) >= theTexture.get_height()) return ", metalReturnName, "(0);\n"));
+                if (locationVectorLength >= 3)
+                    stringBuilder.append(makeString("    if (location.z < 0 || static_cast<uint32_t>(location.z) >= theTexture.get_depth()) return ", metalReturnName, "(0);\n"));
+            }
+        }
+        stringBuilder.append("    return theTexture.read(");
+        if (textureType.isTextureArray()) {
+            ASSERT(locationVectorLength > 1);
+            stringBuilder.append(makeString("uint", vectorSuffix(locationVectorLength - 1), "(location.", "xyzw"_str.substring(0, locationVectorLength - 1), "), uint(location.", "xyzw"_str.substring(locationVectorLength - 1, 1), ")"));
+        } else
+            stringBuilder.append(makeString("uint", vectorSuffix(locationVectorLength), "(location)"));
+        stringBuilder.append(")");
+        if (!textureType.isDepthTexture())
+            stringBuilder.append(makeString(".", "xyzw"_str.substring(0, returnVectorLength)));
+        stringBuilder.append(";\n");
+        stringBuilder.append("}\n");
+        return stringBuilder.toString();
     }
 
     if (nativeFunctionDeclaration.name() == "GetDimensions") {
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195813 Implement this
-        notImplemented();
+        auto& textureType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[0]->type()->unifyNode()));
+
+        size_t index = 1;
+        if (!textureType.isWritableTexture() && textureType.textureDimension() != 1)
+            ++index;
+        auto widthTypeName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[index]->type());
+        ++index;
+        String heightTypeName;
+        if (textureType.textureDimension() >= 2) {
+            heightTypeName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[index]->type());
+            ++index;
+        }
+        String depthTypeName;
+        if (textureType.textureDimension() >= 3) {
+            depthTypeName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[index]->type());
+            ++index;
+        }
+        String elementsTypeName;
+        if (textureType.isTextureArray()) {
+            elementsTypeName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[index]->type());
+            ++index;
+        }
+        String numberOfLevelsTypeName;
+        if (!textureType.isWritableTexture()) {
+            numberOfLevelsTypeName = typeNamer.mangledNameForType(*nativeFunctionDeclaration.parameters()[index]->type());
+            ++index;
+        }
+        ASSERT(index == nativeFunctionDeclaration.parameters().size());
+
+        auto metalParameter1Name = typeNamer.mangledNameForType(textureType);
+        stringBuilder.append(makeString("void ", outputFunctionName, '(', metalParameter1Name, " theTexture"));
+        if (!textureType.isWritableTexture() && textureType.textureDimension() != 1)
+            stringBuilder.append(", uint mipLevel");
+        stringBuilder.append(makeString(", ", widthTypeName, " width"));
+        if (!heightTypeName.isNull())
+            stringBuilder.append(makeString(", ", heightTypeName, " height"));
+        if (!depthTypeName.isNull())
+            stringBuilder.append(makeString(", ", depthTypeName, " depth"));
+        if (!elementsTypeName.isNull())
+            stringBuilder.append(makeString(", ", elementsTypeName, " elements"));
+        if (!numberOfLevelsTypeName.isNull())
+            stringBuilder.append(makeString(", ", numberOfLevelsTypeName, " numberOfLevels"));
+        stringBuilder.append(") {\n");
+        stringBuilder.append("    if (width)\n");
+        stringBuilder.append("        *width = theTexture.get_width(");
+        if (!textureType.isWritableTexture() && textureType.textureDimension() != 1)
+            stringBuilder.append("mipLevel");
+        stringBuilder.append(");\n");
+        if (!heightTypeName.isNull()) {
+            stringBuilder.append("    if (height)\n");
+            stringBuilder.append("        *height = theTexture.get_height(");
+            if (!textureType.isWritableTexture() && textureType.textureDimension() != 1)
+                stringBuilder.append("mipLevel");
+            stringBuilder.append(");\n");
+        }
+        if (!depthTypeName.isNull()) {
+            stringBuilder.append("    if (depth)\n");
+            stringBuilder.append("        *depth = theTexture.get_depth(");
+            if (!textureType.isWritableTexture() && textureType.textureDimension() != 1)
+                stringBuilder.append("mipLevel");
+            stringBuilder.append(");\n");
+        }
+        if (!elementsTypeName.isNull()) {
+            stringBuilder.append("    if (elements)\n");
+            stringBuilder.append("        *elements = theTexture.get_array_size();\n");
+        }
+        if (!numberOfLevelsTypeName.isNull()) {
+            stringBuilder.append("    if (numberOfLevels)\n");
+            stringBuilder.append("        *numberOfLevels = theTexture.get_num_mip_levels();\n");
+        }
+        stringBuilder.append("}\n");
+        return stringBuilder.toString();
     }
 
     if (nativeFunctionDeclaration.name() == "SampleBias") {
@@ -439,8 +617,51 @@ String writeNativeFunction(AST::NativeFunctionDeclaration& nativeFunctionDeclara
     }
 
     if (nativeFunctionDeclaration.name() == "Store") {
-        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195813 Implement this
-        notImplemented();
+        ASSERT(nativeFunctionDeclaration.parameters().size() == 3);
+        
+        auto& textureType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[0]->type()->unifyNode()));
+        auto& itemType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[1]->type()->unifyNode()));
+        auto& itemVectorInnerType = vectorInnerType(itemType);
+        auto itemVectorLength = vectorLength(itemType);
+        auto& locationType = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(nativeFunctionDeclaration.parameters()[2]->type()->unifyNode()));
+        auto locationVectorLength = vectorLength(locationType);
+
+        auto metalParameter1Name = typeNamer.mangledNameForType(textureType);
+        auto metalParameter2Name = typeNamer.mangledNameForType(itemType);
+        auto metalParameter3Name = typeNamer.mangledNameForType(locationType);
+        auto metalInnerTypeName = typeNamer.mangledNameForType(itemVectorInnerType);
+        stringBuilder.append(makeString("void ", outputFunctionName, '(', metalParameter1Name, " theTexture, ", metalParameter2Name, " item, ", metalParameter3Name, " location) {\n"));
+        if (textureType.isTextureArray()) {
+            ASSERT(locationVectorLength > 1);
+            String dimensions[] = { "width"_str, "height"_str, "depth"_str };
+            for (int i = 0; i < locationVectorLength - 1; ++i) {
+                auto suffix = "xyzw"_str.substring(i, 1);
+                stringBuilder.append(makeString("    if (location.", suffix, " >= theTexture.get_", dimensions[i], "()) return;\n"));
+            }
+            auto suffix = "xyzw"_str.substring(locationVectorLength - 1, 1);
+            stringBuilder.append(makeString("    if (location.", suffix, " >= theTexture.get_array_size()) return;\n"));
+        } else {
+            if (locationVectorLength == 1)
+                stringBuilder.append(makeString("    if (location >= theTexture.get_width()) return;\n"));
+            else {
+                stringBuilder.append(makeString("    if (location.x >= theTexture.get_width()) return;\n"));
+                stringBuilder.append(makeString("    if (location.y >= theTexture.get_height()) return;\n"));
+                if (locationVectorLength >= 3)
+                    stringBuilder.append(makeString("    if (location.z >= theTexture.get_depth()) return;\n"));
+            }
+        }
+        stringBuilder.append(makeString("    theTexture.write(vec<", metalInnerTypeName, ", 4>(item"));
+        for (int i = 0; i < 4 - itemVectorLength; ++i)
+            stringBuilder.append(", 0");
+        stringBuilder.append("), ");
+        if (textureType.isTextureArray()) {
+            ASSERT(locationVectorLength > 1);
+            stringBuilder.append(makeString("uint", vectorSuffix(locationVectorLength - 1), "(location.", "xyzw"_str.substring(0, locationVectorLength - 1), "), uint(location.", "xyzw"_str.substring(locationVectorLength - 1, 1), ")"));
+        } else
+            stringBuilder.append(makeString("uint", vectorSuffix(locationVectorLength), "(location)"));
+        stringBuilder.append(");\n");
+        stringBuilder.append("}\n");
+        return stringBuilder.toString();
     }
 
     if (nativeFunctionDeclaration.name() == "GatherAlpha") {
index f57d5c0..ebfe61d 100644 (file)
@@ -180,12 +180,8 @@ String writeNativeType(AST::NativeTypeDeclaration& nativeTypeDeclaration)
             return "texturecube"_str;
         if (nativeTypeDeclaration.name() == "TextureDepth2D")
             return "depth2d"_str;
-        if (nativeTypeDeclaration.name() == "RWTextureDepth2D")
-            return "depth2d"_str;
         if (nativeTypeDeclaration.name() == "TextureDepth2DArray")
             return "depth2d_array"_str;
-        if (nativeTypeDeclaration.name() == "RWTextureDepth2DArray")
-            return "depth2d_array"_str;
         ASSERT(nativeTypeDeclaration.name() == "TextureDepthCube");
         return "depthcube"_str;
     })();
@@ -239,8 +235,12 @@ String writeNativeType(AST::NativeTypeDeclaration& nativeTypeDeclaration)
         ASSERT(typeReference->name() == "float4");
         return "float"_str;
     })();
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195813 Specify the second template argument to Metal texture types.
-    return makeString(prefix, '<', innerType, '>');
+    auto isReadWrite = nativeTypeDeclaration.name() == "RWTexture1D"
+        || nativeTypeDeclaration.name() == "RWTexture1DArray"
+        || nativeTypeDeclaration.name() == "RWTexture2D"
+        || nativeTypeDeclaration.name() == "RWTexture2DArray"
+        || nativeTypeDeclaration.name() == "RWTexture3D";
+    return makeString(prefix, '<', innerType, ", ", isReadWrite ? "access::read_write" : "access::sample", '>');
 }
 
 } // namespace Metal
index b22957a..eab71b3 100644 (file)
@@ -75,7 +75,10 @@ private:
         callExpression->setOverloads(m_castFunctions);
         Vector<std::reference_wrapper<ResolvingType>> argumentTypes;
         auto* function = resolveFunctionOverload(*callExpression->overloads(), argumentTypes, type);
-        RELEASE_ASSERT(function);
+        if (!function) {
+            setError();
+            return;
+        }
         callExpression->setFunction(*function);
 
         variableDeclaration.setInitializer(WTFMove(callExpression));
@@ -85,10 +88,11 @@ private:
     Vector<std::reference_wrapper<AST::FunctionDeclaration>, 1>& m_castFunctions;
 };
 
-void autoInitializeVariables(Program& program)
+bool autoInitializeVariables(Program& program)
 {
     AutoInitialize autoInitialize(program.nameContext());
     autoInitialize.Visitor::visit(program);
+    return !autoInitialize.error();
 }
 
 } // namespace WHLSL
index f2eac33..29aabb0 100644 (file)
@@ -33,7 +33,7 @@ namespace WHLSL {
 
 class Program;
 
-void autoInitializeVariables(Program&);
+bool autoInitializeVariables(Program&);
 
 }
 
index eda00ba..7c6db8b 100644 (file)
@@ -141,6 +141,14 @@ bool checkDuplicateFunctions(const Program& program)
             && is<AST::ReferenceType>(static_cast<const AST::UnnamedType&>(*function.parameters()[1]->type()))
             && matches(*function.parameters()[0]->type(), *function.parameters()[1]->type()))
             return false;
+        else if (function.isCast() && function.parameters().isEmpty()) {
+            auto& unifyNode = function.type().unifyNode();
+            if (is<AST::NamedType>(unifyNode) && is<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(unifyNode))) {
+                auto& nativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(downcast<AST::NamedType>(unifyNode));
+                if (nativeTypeDeclaration.isOpaqueType())
+                    return false;
+            }
+        }
 
         return true;
     };
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp
new file mode 100644 (file)
index 0000000..c02db89
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WHLSLCheckTextureReferences.h"
+
+#include "WHLSLInferTypes.h"
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+
+namespace WHLSL {
+
+class TextureReferencesChecker : public Visitor {
+public:
+    TextureReferencesChecker() = default;
+
+    virtual ~TextureReferencesChecker() = default;
+
+private:
+    void visit(AST::PointerType&) override;
+    void visit(AST::ArrayReferenceType&) override;
+    void visit(AST::ArrayType&) override;
+    void visit(AST::Expression&) override;
+
+    bool containsTextureOrSampler(AST::UnnamedType&);
+};
+
+class Searcher : public Visitor {
+public:
+    Searcher() = default;
+
+    virtual ~Searcher() = default;
+
+    bool found() const { return m_found; }
+
+private:
+    void visit(AST::NativeTypeDeclaration&);
+
+    bool m_found { false };
+};
+
+void Searcher::visit(AST::NativeTypeDeclaration& nativeTypeDeclaration)
+{
+    if (nativeTypeDeclaration.isOpaqueType())
+        m_found = true;
+}
+
+bool TextureReferencesChecker::containsTextureOrSampler(AST::UnnamedType& unnamedType)
+{
+    Searcher searcher;
+    searcher.checkErrorAndVisit(unnamedType);
+    return searcher.found();
+}
+
+void TextureReferencesChecker::visit(AST::PointerType& pointerType)
+{
+    Visitor::visit(pointerType);
+    if (error())
+        return;
+    if (containsTextureOrSampler(pointerType.elementType()))
+        setError();
+}
+
+void TextureReferencesChecker::visit(AST::ArrayReferenceType& arrayReferenceType)
+{
+    Visitor::visit(arrayReferenceType);
+    if (error())
+        return;
+    if (containsTextureOrSampler(arrayReferenceType.elementType()))
+        setError();
+}
+
+void TextureReferencesChecker::visit(AST::ArrayType& arrayType)
+{
+    Visitor::visit(arrayType);
+    if (error())
+        return;
+    if (containsTextureOrSampler(arrayType.type()))
+        setError();
+}
+
+void TextureReferencesChecker::visit(AST::Expression& expression)
+{
+    Visitor::visit(expression);
+    checkErrorAndVisit(expression.resolvedType());
+}
+
+bool checkTextureReferences(Program& program)
+{
+    TextureReferencesChecker textureReferencesChecker;
+    textureReferencesChecker.checkErrorAndVisit(program);
+    return !textureReferencesChecker.error();
+}
+
+} // namespace WHLSL
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.h
new file mode 100644 (file)
index 0000000..5327fab
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+
+namespace WHLSL {
+
+class Program;
+
+bool checkTextureReferences(Program&);
+
+}
+
+}
+
+#endif
index c05c733..6b2bb04 100644 (file)
@@ -452,7 +452,7 @@ public:
     {
     }
 
-    ~Checker() = default;
+    virtual ~Checker() = default;
 
     void visit(Program&) override;
 
index c8bffb8..36f9d3b 100644 (file)
@@ -272,8 +272,10 @@ bool Intrinsics::addPrimitive(AST::NativeTypeDeclaration& nativeTypeDeclaration)
     } else if (nativeTypeDeclaration.name() == "atomic_uint") {
         nativeTypeDeclaration.setIsAtomic();
         m_atomicUintType = &nativeTypeDeclaration;
-    } else if (nativeTypeDeclaration.name() == "sampler")
+    } else if (nativeTypeDeclaration.name() == "sampler") {
         m_samplerType = &nativeTypeDeclaration;
+        nativeTypeDeclaration.setIsOpaqueType();
+    }
     else
         ASSERT_NOT_REACHED();
     return true;
@@ -369,6 +371,17 @@ bool Intrinsics::addFullTexture(AST::NativeTypeDeclaration& nativeTypeDeclaratio
     }
     ASSERT(innerTypeIndex != WTF_ARRAY_LENGTH(m_textureInnerTypeNames));
     nativeTypeDeclaration.setIsTexture();
+    nativeTypeDeclaration.setIsOpaqueType();
+    if (nativeTypeDeclaration.name() == "Texture1DArray" || nativeTypeDeclaration.name() == "RWTexture1DArray" || nativeTypeDeclaration.name() == "Texture2DArray" || nativeTypeDeclaration.name() == "RWTexture2DArray")
+        nativeTypeDeclaration.setIsTextureArray();
+    if (nativeTypeDeclaration.name() == "RWTexture1D" || nativeTypeDeclaration.name() == "RWTexture2D" || nativeTypeDeclaration.name() == "RWTexture3D" || nativeTypeDeclaration.name() == "RWTexture1DArray" || nativeTypeDeclaration.name() == "RWTexture2DArray")
+        nativeTypeDeclaration.setIsWritableTexture();
+    if (nativeTypeDeclaration.name() == "Texture1D" || nativeTypeDeclaration.name() == "RWTexture1D" || nativeTypeDeclaration.name() == "Texture1DArray" || nativeTypeDeclaration.name() == "RWTexture1DArray")
+        nativeTypeDeclaration.setTextureDimension(1);
+    if (nativeTypeDeclaration.name() == "Texture2D" || nativeTypeDeclaration.name() == "RWTexture2D" || nativeTypeDeclaration.name() == "TextureCube" || nativeTypeDeclaration.name() == "Texture2DArray" || nativeTypeDeclaration.name() == "RWTexture2DArray")
+        nativeTypeDeclaration.setTextureDimension(2);
+    if (nativeTypeDeclaration.name() == "Texture3D" || nativeTypeDeclaration.name() == "RWTexture3D")
+        nativeTypeDeclaration.setTextureDimension(3);
     m_fullTextures[textureTypeIndex][innerTypeIndex][vectorLength - 1] = &nativeTypeDeclaration;
     return true;
 }
@@ -378,12 +391,8 @@ void Intrinsics::addDepthTexture(AST::NativeTypeDeclaration& nativeTypeDeclarati
     AST::NativeTypeDeclaration** texture = nullptr;
     if (nativeTypeDeclaration.name() == "TextureDepth2D")
         texture = m_textureDepth2D;
-    else if (nativeTypeDeclaration.name() == "RWTextureDepth2D")
-        texture = m_rwTextureDepth2D;
     else if (nativeTypeDeclaration.name() == "TextureDepth2DArray")
         texture = m_textureDepth2DArray;
-    else if (nativeTypeDeclaration.name() == "RWTextureDepth2DArray")
-        texture = m_rwTextureDepth2DArray;
     else {
         ASSERT(nativeTypeDeclaration.name() == "TextureDepthCube");
         texture = m_textureDepthCube;
@@ -391,6 +400,11 @@ void Intrinsics::addDepthTexture(AST::NativeTypeDeclaration& nativeTypeDeclarati
     auto innerTypeIndex = std::find(m_depthTextureInnerTypes, m_depthTextureInnerTypes + WTF_ARRAY_LENGTH(m_depthTextureInnerTypes), innerType.name()) - m_depthTextureInnerTypes;
     ASSERT(innerTypeIndex != WTF_ARRAY_LENGTH(m_depthTextureInnerTypes));
     nativeTypeDeclaration.setIsTexture();
+    nativeTypeDeclaration.setIsOpaqueType();
+    if (texture == m_textureDepth2DArray)
+        nativeTypeDeclaration.setIsTextureArray();
+    nativeTypeDeclaration.setTextureDimension(2);
+    nativeTypeDeclaration.setIsDepthTexture();
     texture[innerTypeIndex] = &nativeTypeDeclaration;
 }
 
index ad857c5..f08022c 100644 (file)
@@ -263,7 +263,7 @@ private:
     AST::NativeTypeDeclaration* m_matrixHalf[3][3] {{ 0 }};
     AST::NativeTypeDeclaration* m_matrixFloat[3][3] {{ 0 }};
 
-    static constexpr const char* m_textureTypeNames[] = { "Texture1D", "RWTexture1D", "Texture1DArray", "RWTexture1DArray", "Texture2D", "RWTexture2D", "Texture2DArray", "RWTexture2DArray", "Texture3D", "RWTexture3D", "TextureCube" };
+    static constexpr const char* m_textureTypeNames[] = { "Texture1D", "RWTexture1D", "Texture2D", "RWTexture2D", "Texture3D", "RWTexture3D", "TextureCube", "Texture1DArray", "RWTexture1DArray", "Texture2DArray", "RWTexture2DArray" };
 
     static constexpr const char* m_textureInnerTypeNames[] = { "uchar", "ushort",  "uint", "char", "short", "int", "half", "float" };
 
@@ -272,9 +272,7 @@ private:
     static constexpr const char* m_depthTextureInnerTypes[] =  { "half", "float" };
 
     AST::NativeTypeDeclaration* m_textureDepth2D[WTF_ARRAY_LENGTH(m_depthTextureInnerTypes)] { 0 };
-    AST::NativeTypeDeclaration* m_rwTextureDepth2D[WTF_ARRAY_LENGTH(m_depthTextureInnerTypes)] { 0 };
     AST::NativeTypeDeclaration* m_textureDepth2DArray[WTF_ARRAY_LENGTH(m_depthTextureInnerTypes)] { 0 };
-    AST::NativeTypeDeclaration* m_rwTextureDepth2DArray[WTF_ARRAY_LENGTH(m_depthTextureInnerTypes)] { 0 };
     AST::NativeTypeDeclaration* m_textureDepthCube[WTF_ARRAY_LENGTH(m_depthTextureInnerTypes)] { 0 };
 
     AST::NativeFunctionDeclaration* m_ddx { nullptr };
index 7ee4000..d875da8 100644 (file)
@@ -58,11 +58,18 @@ NameResolver::NameResolver(NameContext& nameContext)
 
 NameResolver::NameResolver(NameResolver& parentResolver, NameContext& nameContext)
     : m_nameContext(nameContext)
+    , m_parentNameResolver(&parentResolver)
 {
     m_isResolvingCalls = parentResolver.m_isResolvingCalls;
     setCurrentFunctionDefinition(parentResolver.m_currentFunction);
 }
 
+NameResolver::~NameResolver()
+{
+    if (error() && m_parentNameResolver)
+        m_parentNameResolver->setError();
+}
+
 void NameResolver::visit(AST::TypeReference& typeReference)
 {
     if (m_isResolvingCalls)
@@ -116,7 +123,9 @@ void NameResolver::visit(AST::IfStatement& ifStatement)
     NameContext nameContext(&m_nameContext);
     NameResolver newNameResolver(*this, nameContext);
     newNameResolver.checkErrorAndVisit(ifStatement.body());
-    if (ifStatement.elseBody()) {
+    if (newNameResolver.error())
+        setError();
+    else if (ifStatement.elseBody()) {
         NameContext nameContext(&m_nameContext);
         NameResolver newNameResolver(*this, nameContext);
         newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
@@ -258,6 +267,13 @@ void NameResolver::visit(AST::EnumerationMemberLiteral& enumerationMemberLiteral
     setError();
 }
 
+void NameResolver::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
+{
+    NameContext newNameContext(&m_nameContext);
+    NameResolver newNameResolver(newNameContext);
+    newNameResolver.Visitor::visit(nativeFunctionDeclaration);
+}
+
 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=198167 Make sure all the names have been resolved.
 
 bool resolveNamesInTypes(Program& program, NameResolver& nameResolver)
index a718bda..91faacc 100644 (file)
@@ -42,7 +42,7 @@ public:
     NameResolver(NameContext&);
     NameResolver(NameResolver&, NameContext&);
 
-    virtual ~NameResolver() = default;
+    virtual ~NameResolver();
 
     void visit(AST::FunctionDefinition&) override;
 
@@ -54,6 +54,7 @@ public:
     void setIsResolvingCalls(bool isResolvingCalls) { m_isResolvingCalls = isResolvingCalls; }
 
 private:
+    void visit(AST::NativeFunctionDeclaration&) override;
     void visit(AST::TypeReference&) override;
     void visit(AST::Block&) override;
     void visit(AST::IfStatement&) override;
@@ -71,6 +72,7 @@ private:
     NameContext& m_nameContext;
     HashSet<AST::TypeReference*> m_typeReferences;
     AST::FunctionDefinition* m_currentFunction { nullptr };
+    NameResolver* m_parentNameResolver { nullptr };
     bool m_isResolvingCalls { false };
 };
 
index 6d53239..aca90aa 100644 (file)
@@ -31,6 +31,7 @@
 #include "WHLSLASTDumper.h"
 #include "WHLSLAutoInitializeVariables.h"
 #include "WHLSLCheckDuplicateFunctions.h"
+#include "WHLSLCheckTextureReferences.h"
 #include "WHLSLChecker.h"
 #include "WHLSLComputeDimensions.h"
 #include "WHLSLFunctionStageChecker.h"
@@ -133,7 +134,8 @@ static Optional<Program> prepareShared(String& whlslSource)
     RUN_PASS(check, program);
 
     checkLiteralTypes(program);
-    autoInitializeVariables(program);
+    RUN_PASS(checkTextureReferences, program);
+    RUN_PASS(autoInitializeVariables, program);
     resolveProperties(program);
     findHighZombies(program);
     RUN_PASS(checkStatementBehavior, program);
index 5d4bda1..40baf09 100644 (file)
@@ -86,6 +86,7 @@ public:
 
     NameContext& nameContext() { return m_nameContext; }
     Intrinsics& intrinsics() { return m_intrinsics; }
+    const Intrinsics& intrinsics() const { return m_intrinsics; }
     Vector<UniqueRef<AST::TypeDefinition>>& typeDefinitions() { return m_typeDefinitions; }
     Vector<UniqueRef<AST::StructureDefinition>>& structureDefinitions() { return m_structureDefinitions; }
     Vector<UniqueRef<AST::EnumerationDefinition>>& enumerationDefinitions() { return m_enumerationDefinitions; }
index 12a7048..2b91b95 100644 (file)
@@ -41,7 +41,7 @@ namespace WHLSL {
 
 class RecursiveTypeChecker : public Visitor {
 public:
-    ~RecursiveTypeChecker() = default;
+    virtual ~RecursiveTypeChecker() = default;
 
     void visit(AST::TypeDefinition&) override;
     void visit(AST::StructureDefinition&) override;
index 8771fc0..c4ca0c3 100644 (file)
@@ -129,30 +129,6 @@ native typedef Texture1D<float>;
 native typedef Texture1D<float2>;
 native typedef Texture1D<float3>;
 native typedef Texture1D<float4>;
-native typedef RWTexture1D<ushort>;
-native typedef RWTexture1D<ushort2>;
-native typedef RWTexture1D<ushort3>;
-native typedef RWTexture1D<ushort4>;
-native typedef RWTexture1D<uint>;
-native typedef RWTexture1D<uint2>;
-native typedef RWTexture1D<uint3>;
-native typedef RWTexture1D<uint4>;
-native typedef RWTexture1D<short>;
-native typedef RWTexture1D<short2>;
-native typedef RWTexture1D<short3>;
-native typedef RWTexture1D<short4>;
-native typedef RWTexture1D<int>;
-native typedef RWTexture1D<int2>;
-native typedef RWTexture1D<int3>;
-native typedef RWTexture1D<int4>;
-native typedef RWTexture1D<half>;
-native typedef RWTexture1D<half2>;
-native typedef RWTexture1D<half3>;
-native typedef RWTexture1D<half4>;
-native typedef RWTexture1D<float>;
-native typedef RWTexture1D<float2>;
-native typedef RWTexture1D<float3>;
-native typedef RWTexture1D<float4>;
 native typedef Texture1DArray<ushort>;
 native typedef Texture1DArray<ushort2>;
 native typedef Texture1DArray<ushort3>;
@@ -177,30 +153,6 @@ native typedef Texture1DArray<float>;
 native typedef Texture1DArray<float2>;
 native typedef Texture1DArray<float3>;
 native typedef Texture1DArray<float4>;
-native typedef RWTexture1DArray<ushort>;
-native typedef RWTexture1DArray<ushort2>;
-native typedef RWTexture1DArray<ushort3>;
-native typedef RWTexture1DArray<ushort4>;
-native typedef RWTexture1DArray<uint>;
-native typedef RWTexture1DArray<uint2>;
-native typedef RWTexture1DArray<uint3>;
-native typedef RWTexture1DArray<uint4>;
-native typedef RWTexture1DArray<short>;
-native typedef RWTexture1DArray<short2>;
-native typedef RWTexture1DArray<short3>;
-native typedef RWTexture1DArray<short4>;
-native typedef RWTexture1DArray<int>;
-native typedef RWTexture1DArray<int2>;
-native typedef RWTexture1DArray<int3>;
-native typedef RWTexture1DArray<int4>;
-native typedef RWTexture1DArray<half>;
-native typedef RWTexture1DArray<half2>;
-native typedef RWTexture1DArray<half3>;
-native typedef RWTexture1DArray<half4>;
-native typedef RWTexture1DArray<float>;
-native typedef RWTexture1DArray<float2>;
-native typedef RWTexture1DArray<float3>;
-native typedef RWTexture1DArray<float4>;
 native typedef Texture2D<ushort>;
 native typedef Texture2D<ushort2>;
 native typedef Texture2D<ushort3>;
@@ -225,30 +177,6 @@ native typedef Texture2D<float>;
 native typedef Texture2D<float2>;
 native typedef Texture2D<float3>;
 native typedef Texture2D<float4>;
-native typedef RWTexture2D<ushort>;
-native typedef RWTexture2D<ushort2>;
-native typedef RWTexture2D<ushort3>;
-native typedef RWTexture2D<ushort4>;
-native typedef RWTexture2D<uint>;
-native typedef RWTexture2D<uint2>;
-native typedef RWTexture2D<uint3>;
-native typedef RWTexture2D<uint4>;
-native typedef RWTexture2D<short>;
-native typedef RWTexture2D<short2>;
-native typedef RWTexture2D<short3>;
-native typedef RWTexture2D<short4>;
-native typedef RWTexture2D<int>;
-native typedef RWTexture2D<int2>;
-native typedef RWTexture2D<int3>;
-native typedef RWTexture2D<int4>;
-native typedef RWTexture2D<half>;
-native typedef RWTexture2D<half2>;
-native typedef RWTexture2D<half3>;
-native typedef RWTexture2D<half4>;
-native typedef RWTexture2D<float>;
-native typedef RWTexture2D<float2>;
-native typedef RWTexture2D<float3>;
-native typedef RWTexture2D<float4>;
 native typedef Texture2DArray<ushort>;
 native typedef Texture2DArray<ushort2>;
 native typedef Texture2DArray<ushort3>;
@@ -273,30 +201,6 @@ native typedef Texture2DArray<float>;
 native typedef Texture2DArray<float2>;
 native typedef Texture2DArray<float3>;
 native typedef Texture2DArray<float4>;
-native typedef RWTexture2DArray<ushort>;
-native typedef RWTexture2DArray<ushort2>;
-native typedef RWTexture2DArray<ushort3>;
-native typedef RWTexture2DArray<ushort4>;
-native typedef RWTexture2DArray<uint>;
-native typedef RWTexture2DArray<uint2>;
-native typedef RWTexture2DArray<uint3>;
-native typedef RWTexture2DArray<uint4>;
-native typedef RWTexture2DArray<short>;
-native typedef RWTexture2DArray<short2>;
-native typedef RWTexture2DArray<short3>;
-native typedef RWTexture2DArray<short4>;
-native typedef RWTexture2DArray<int>;
-native typedef RWTexture2DArray<int2>;
-native typedef RWTexture2DArray<int3>;
-native typedef RWTexture2DArray<int4>;
-native typedef RWTexture2DArray<half>;
-native typedef RWTexture2DArray<half2>;
-native typedef RWTexture2DArray<half3>;
-native typedef RWTexture2DArray<half4>;
-native typedef RWTexture2DArray<float>;
-native typedef RWTexture2DArray<float2>;
-native typedef RWTexture2DArray<float3>;
-native typedef RWTexture2DArray<float4>;
 native typedef Texture3D<ushort>;
 native typedef Texture3D<ushort2>;
 native typedef Texture3D<ushort3>;
@@ -321,30 +225,6 @@ native typedef Texture3D<float>;
 native typedef Texture3D<float2>;
 native typedef Texture3D<float3>;
 native typedef Texture3D<float4>;
-native typedef RWTexture3D<ushort>;
-native typedef RWTexture3D<ushort2>;
-native typedef RWTexture3D<ushort3>;
-native typedef RWTexture3D<ushort4>;
-native typedef RWTexture3D<uint>;
-native typedef RWTexture3D<uint2>;
-native typedef RWTexture3D<uint3>;
-native typedef RWTexture3D<uint4>;
-native typedef RWTexture3D<short>;
-native typedef RWTexture3D<short2>;
-native typedef RWTexture3D<short3>;
-native typedef RWTexture3D<short4>;
-native typedef RWTexture3D<int>;
-native typedef RWTexture3D<int2>;
-native typedef RWTexture3D<int3>;
-native typedef RWTexture3D<int4>;
-native typedef RWTexture3D<half>;
-native typedef RWTexture3D<half2>;
-native typedef RWTexture3D<half3>;
-native typedef RWTexture3D<half4>;
-native typedef RWTexture3D<float>;
-native typedef RWTexture3D<float2>;
-native typedef RWTexture3D<float3>;
-native typedef RWTexture3D<float4>;
 native typedef TextureCube<ushort>;
 native typedef TextureCube<ushort2>;
 native typedef TextureCube<ushort3>;
@@ -370,9 +250,7 @@ native typedef TextureCube<float2>;
 native typedef TextureCube<float3>;
 native typedef TextureCube<float4>;
 native typedef TextureDepth2D<float>;
-native typedef RWTextureDepth2D<float>;
 native typedef TextureDepth2DArray<float>;
-native typedef RWTextureDepth2DArray<float>;
 native typedef TextureDepthCube<float>;
 
 native operator uchar(ushort);
@@ -848,4 +726,406 @@ float4x4 mul(float4x4 x, float4x4 y) {
     return result;
 }
 
+operator float2(float x, float y) {
+    float2 result;
+    result.x = x;
+    result.y = y;
+    return result;
+}
+
+operator int3(int x, int y, int z) {
+    int3 result;
+    result.x = x;
+    result.y = y;
+    result.z = z;
+    return result;
+}
+
+operator int2(int x, int y) {
+    int2 result;
+    result.x = x;
+    result.y = y;
+    return result;
+}
+
+operator uint2(uint x, uint y) {
+    uint2 result;
+    result.x = x;
+    result.y = y;
+    return result;
+}
+
+native ushort Sample(Texture1D<ushort>, sampler, float location);
+native ushort Sample(Texture1DArray<ushort>, sampler, float2 location);
+native ushort Sample(Texture2D<ushort>, sampler, float2 location);
+native ushort Sample(Texture2D<ushort>, sampler, float2 location, int2 offset);
+native ushort Sample(Texture2DArray<ushort>, sampler, float3 location);
+native ushort Sample(Texture2DArray<ushort>, sampler, float3 location, int2 offset);
+native ushort Sample(Texture3D<ushort>, sampler, float3 location);
+native ushort Sample(Texture3D<ushort>, sampler, float3 location, int3 offset);
+native ushort Sample(TextureCube<ushort>, sampler, float3 location);
+native ushort2 Sample(Texture1D<ushort2>, sampler, float location);
+native ushort2 Sample(Texture1DArray<ushort2>, sampler, float2 location);
+native ushort2 Sample(Texture2D<ushort2>, sampler, float2 location);
+native ushort2 Sample(Texture2D<ushort2>, sampler, float2 location, int2 offset);
+native ushort2 Sample(Texture2DArray<ushort2>, sampler, float3 location);
+native ushort2 Sample(Texture2DArray<ushort2>, sampler, float3 location, int2 offset);
+native ushort2 Sample(Texture3D<ushort2>, sampler, float3 location);
+native ushort2 Sample(Texture3D<ushort2>, sampler, float3 location, int3 offset);
+native ushort2 Sample(TextureCube<ushort2>, sampler, float3 location);
+native ushort3 Sample(Texture1D<ushort3>, sampler, float location);
+native ushort3 Sample(Texture1DArray<ushort3>, sampler, float2 location);
+native ushort3 Sample(Texture2D<ushort3>, sampler, float2 location);
+native ushort3 Sample(Texture2D<ushort3>, sampler, float2 location, int2 offset);
+native ushort3 Sample(Texture2DArray<ushort3>, sampler, float3 location);
+native ushort3 Sample(Texture2DArray<ushort3>, sampler, float3 location, int2 offset);
+native ushort3 Sample(Texture3D<ushort3>, sampler, float3 location);
+native ushort3 Sample(Texture3D<ushort3>, sampler, float3 location, int3 offset);
+native ushort3 Sample(TextureCube<ushort3>, sampler, float3 location);
+native ushort4 Sample(Texture1D<ushort4>, sampler, float location);
+native ushort4 Sample(Texture1DArray<ushort4>, sampler, float2 location);
+native ushort4 Sample(Texture2D<ushort4>, sampler, float2 location);
+native ushort4 Sample(Texture2D<ushort4>, sampler, float2 location, int2 offset);
+native ushort4 Sample(Texture2DArray<ushort4>, sampler, float3 location);
+native ushort4 Sample(Texture2DArray<ushort4>, sampler, float3 location, int2 offset);
+native ushort4 Sample(Texture3D<ushort4>, sampler, float3 location);
+native ushort4 Sample(Texture3D<ushort4>, sampler, float3 location, int3 offset);
+native ushort4 Sample(TextureCube<ushort4>, sampler, float3 location);
+native uint Sample(Texture1D<uint>, sampler, float location);
+native uint Sample(Texture1DArray<uint>, sampler, float2 location);
+native uint Sample(Texture2D<uint>, sampler, float2 location);
+native uint Sample(Texture2D<uint>, sampler, float2 location, int2 offset);
+native uint Sample(Texture2DArray<uint>, sampler, float3 location);
+native uint Sample(Texture2DArray<uint>, sampler, float3 location, int2 offset);
+native uint Sample(Texture3D<uint>, sampler, float3 location);
+native uint Sample(Texture3D<uint>, sampler, float3 location, int3 offset);
+native uint Sample(TextureCube<uint>, sampler, float3 location);
+native uint2 Sample(Texture1D<uint2>, sampler, float location);
+native uint2 Sample(Texture1DArray<uint2>, sampler, float2 location);
+native uint2 Sample(Texture2D<uint2>, sampler, float2 location);
+native uint2 Sample(Texture2D<uint2>, sampler, float2 location, int2 offset);
+native uint2 Sample(Texture2DArray<uint2>, sampler, float3 location);
+native uint2 Sample(Texture2DArray<uint2>, sampler, float3 location, int2 offset);
+native uint2 Sample(Texture3D<uint2>, sampler, float3 location);
+native uint2 Sample(Texture3D<uint2>, sampler, float3 location, int3 offset);
+native uint2 Sample(TextureCube<uint2>, sampler, float3 location);
+native uint3 Sample(Texture1D<uint3>, sampler, float location);
+native uint3 Sample(Texture1DArray<uint3>, sampler, float2 location);
+native uint3 Sample(Texture2D<uint3>, sampler, float2 location);
+native uint3 Sample(Texture2D<uint3>, sampler, float2 location, int2 offset);
+native uint3 Sample(Texture2DArray<uint3>, sampler, float3 location);
+native uint3 Sample(Texture2DArray<uint3>, sampler, float3 location, int2 offset);
+native uint3 Sample(Texture3D<uint3>, sampler, float3 location);
+native uint3 Sample(Texture3D<uint3>, sampler, float3 location, int3 offset);
+native uint3 Sample(TextureCube<uint3>, sampler, float3 location);
+native uint4 Sample(Texture1D<uint4>, sampler, float location);
+native uint4 Sample(Texture1DArray<uint4>, sampler, float2 location);
+native uint4 Sample(Texture2D<uint4>, sampler, float2 location);
+native uint4 Sample(Texture2D<uint4>, sampler, float2 location, int2 offset);
+native uint4 Sample(Texture2DArray<uint4>, sampler, float3 location);
+native uint4 Sample(Texture2DArray<uint4>, sampler, float3 location, int2 offset);
+native uint4 Sample(Texture3D<uint4>, sampler, float3 location);
+native uint4 Sample(Texture3D<uint4>, sampler, float3 location, int3 offset);
+native uint4 Sample(TextureCube<uint4>, sampler, float3 location);
+native short Sample(Texture1D<short>, sampler, float location);
+native short Sample(Texture1DArray<short>, sampler, float2 location);
+native short Sample(Texture2D<short>, sampler, float2 location);
+native short Sample(Texture2D<short>, sampler, float2 location, int2 offset);
+native short Sample(Texture2DArray<short>, sampler, float3 location);
+native short Sample(Texture2DArray<short>, sampler, float3 location, int2 offset);
+native short Sample(Texture3D<short>, sampler, float3 location);
+native short Sample(Texture3D<short>, sampler, float3 location, int3 offset);
+native short Sample(TextureCube<short>, sampler, float3 location);
+native short2 Sample(Texture1D<short2>, sampler, float location);
+native short2 Sample(Texture1DArray<short2>, sampler, float2 location);
+native short2 Sample(Texture2D<short2>, sampler, float2 location);
+native short2 Sample(Texture2D<short2>, sampler, float2 location, int2 offset);
+native short2 Sample(Texture2DArray<short2>, sampler, float3 location);
+native short2 Sample(Texture2DArray<short2>, sampler, float3 location, int2 offset);
+native short2 Sample(Texture3D<short2>, sampler, float3 location);
+native short2 Sample(Texture3D<short2>, sampler, float3 location, int3 offset);
+native short2 Sample(TextureCube<short2>, sampler, float3 location);
+native short3 Sample(Texture1D<short3>, sampler, float location);
+native short3 Sample(Texture1DArray<short3>, sampler, float2 location);
+native short3 Sample(Texture2D<short3>, sampler, float2 location);
+native short3 Sample(Texture2D<short3>, sampler, float2 location, int2 offset);
+native short3 Sample(Texture2DArray<short3>, sampler, float3 location);
+native short3 Sample(Texture2DArray<short3>, sampler, float3 location, int2 offset);
+native short3 Sample(Texture3D<short3>, sampler, float3 location);
+native short3 Sample(Texture3D<short3>, sampler, float3 location, int3 offset);
+native short3 Sample(TextureCube<short3>, sampler, float3 location);
+native short4 Sample(Texture1D<short4>, sampler, float location);
+native short4 Sample(Texture1DArray<short4>, sampler, float2 location);
+native short4 Sample(Texture2D<short4>, sampler, float2 location);
+native short4 Sample(Texture2D<short4>, sampler, float2 location, int2 offset);
+native short4 Sample(Texture2DArray<short4>, sampler, float3 location);
+native short4 Sample(Texture2DArray<short4>, sampler, float3 location, int2 offset);
+native short4 Sample(Texture3D<short4>, sampler, float3 location);
+native short4 Sample(Texture3D<short4>, sampler, float3 location, int3 offset);
+native short4 Sample(TextureCube<short4>, sampler, float3 location);
+native int Sample(Texture1D<int>, sampler, float location);
+native int Sample(Texture1DArray<int>, sampler, float2 location);
+native int Sample(Texture2D<int>, sampler, float2 location);
+native int Sample(Texture2D<int>, sampler, float2 location, int2 offset);
+native int Sample(Texture2DArray<int>, sampler, float3 location);
+native int Sample(Texture2DArray<int>, sampler, float3 location, int2 offset);
+native int Sample(Texture3D<int>, sampler, float3 location);
+native int Sample(Texture3D<int>, sampler, float3 location, int3 offset);
+native int Sample(TextureCube<int>, sampler, float3 location);
+native int2 Sample(Texture1D<int2>, sampler, float location);
+native int2 Sample(Texture1DArray<int2>, sampler, float2 location);
+native int2 Sample(Texture2D<int2>, sampler, float2 location);
+native int2 Sample(Texture2D<int2>, sampler, float2 location, int2 offset);
+native int2 Sample(Texture2DArray<int2>, sampler, float3 location);
+native int2 Sample(Texture2DArray<int2>, sampler, float3 location, int2 offset);
+native int2 Sample(Texture3D<int2>, sampler, float3 location);
+native int2 Sample(Texture3D<int2>, sampler, float3 location, int3 offset);
+native int2 Sample(TextureCube<int2>, sampler, float3 location);
+native int3 Sample(Texture1D<int3>, sampler, float location);
+native int3 Sample(Texture1DArray<int3>, sampler, float2 location);
+native int3 Sample(Texture2D<int3>, sampler, float2 location);
+native int3 Sample(Texture2D<int3>, sampler, float2 location, int2 offset);
+native int3 Sample(Texture2DArray<int3>, sampler, float3 location);
+native int3 Sample(Texture2DArray<int3>, sampler, float3 location, int2 offset);
+native int3 Sample(Texture3D<int3>, sampler, float3 location);
+native int3 Sample(Texture3D<int3>, sampler, float3 location, int3 offset);
+native int3 Sample(TextureCube<int3>, sampler, float3 location);
+native int4 Sample(Texture1D<int4>, sampler, float location);
+native int4 Sample(Texture1DArray<int4>, sampler, float2 location);
+native int4 Sample(Texture2D<int4>, sampler, float2 location);
+native int4 Sample(Texture2D<int4>, sampler, float2 location, int2 offset);
+native int4 Sample(Texture2DArray<int4>, sampler, float3 location);
+native int4 Sample(Texture2DArray<int4>, sampler, float3 location, int2 offset);
+native int4 Sample(Texture3D<int4>, sampler, float3 location);
+native int4 Sample(Texture3D<int4>, sampler, float3 location, int3 offset);
+native int4 Sample(TextureCube<int4>, sampler, float3 location);
+native half Sample(Texture1D<half>, sampler, float location);
+native half Sample(Texture1DArray<half>, sampler, float2 location);
+native half Sample(Texture2D<half>, sampler, float2 location);
+native half Sample(Texture2D<half>, sampler, float2 location, int2 offset);
+native half Sample(Texture2DArray<half>, sampler, float3 location);
+native half Sample(Texture2DArray<half>, sampler, float3 location, int2 offset);
+native half Sample(Texture3D<half>, sampler, float3 location);
+native half Sample(Texture3D<half>, sampler, float3 location, int3 offset);
+native half Sample(TextureCube<half>, sampler, float3 location);
+native half2 Sample(Texture1D<half2>, sampler, float location);
+native half2 Sample(Texture1DArray<half2>, sampler, float2 location);
+native half2 Sample(Texture2D<half2>, sampler, float2 location);
+native half2 Sample(Texture2D<half2>, sampler, float2 location, int2 offset);
+native half2 Sample(Texture2DArray<half2>, sampler, float3 location);
+native half2 Sample(Texture2DArray<half2>, sampler, float3 location, int2 offset);
+native half2 Sample(Texture3D<half2>, sampler, float3 location);
+native half2 Sample(Texture3D<half2>, sampler, float3 location, int3 offset);
+native half2 Sample(TextureCube<half2>, sampler, float3 location);
+native half3 Sample(Texture1D<half3>, sampler, float location);
+native half3 Sample(Texture1DArray<half3>, sampler, float2 location);
+native half3 Sample(Texture2D<half3>, sampler, float2 location);
+native half3 Sample(Texture2D<half3>, sampler, float2 location, int2 offset);
+native half3 Sample(Texture2DArray<half3>, sampler, float3 location);
+native half3 Sample(Texture2DArray<half3>, sampler, float3 location, int2 offset);
+native half3 Sample(Texture3D<half3>, sampler, float3 location);
+native half3 Sample(Texture3D<half3>, sampler, float3 location, int3 offset);
+native half3 Sample(TextureCube<half3>, sampler, float3 location);
+native half4 Sample(Texture1D<half4>, sampler, float location);
+native half4 Sample(Texture1DArray<half4>, sampler, float2 location);
+native half4 Sample(Texture2D<half4>, sampler, float2 location);
+native half4 Sample(Texture2D<half4>, sampler, float2 location, int2 offset);
+native half4 Sample(Texture2DArray<half4>, sampler, float3 location);
+native half4 Sample(Texture2DArray<half4>, sampler, float3 location, int2 offset);
+native half4 Sample(Texture3D<half4>, sampler, float3 location);
+native half4 Sample(Texture3D<half4>, sampler, float3 location, int3 offset);
+native half4 Sample(TextureCube<half4>, sampler, float3 location);
+native float Sample(Texture1D<float>, sampler, float location);
+native float Sample(Texture1DArray<float>, sampler, float2 location);
+native float Sample(Texture2D<float>, sampler, float2 location);
+native float Sample(Texture2D<float>, sampler, float2 location, int2 offset);
+native float Sample(Texture2DArray<float>, sampler, float3 location);
+native float Sample(Texture2DArray<float>, sampler, float3 location, int2 offset);
+native float Sample(Texture3D<float>, sampler, float3 location);
+native float Sample(Texture3D<float>, sampler, float3 location, int3 offset);
+native float Sample(TextureCube<float>, sampler, float3 location);
+native float2 Sample(Texture1D<float2>, sampler, float location);
+native float2 Sample(Texture1DArray<float2>, sampler, float2 location);
+native float2 Sample(Texture2D<float2>, sampler, float2 location);
+native float2 Sample(Texture2D<float2>, sampler, float2 location, int2 offset);
+native float2 Sample(Texture2DArray<float2>, sampler, float3 location);
+native float2 Sample(Texture2DArray<float2>, sampler, float3 location, int2 offset);
+native float2 Sample(Texture3D<float2>, sampler, float3 location);
+native float2 Sample(Texture3D<float2>, sampler, float3 location, int3 offset);
+native float2 Sample(TextureCube<float2>, sampler, float3 location);
+native float3 Sample(Texture1D<float3>, sampler, float location);
+native float3 Sample(Texture1DArray<float3>, sampler, float2 location);
+native float3 Sample(Texture2D<float3>, sampler, float2 location);
+native float3 Sample(Texture2D<float3>, sampler, float2 location, int2 offset);
+native float3 Sample(Texture2DArray<float3>, sampler, float3 location);
+native float3 Sample(Texture2DArray<float3>, sampler, float3 location, int2 offset);
+native float3 Sample(Texture3D<float3>, sampler, float3 location);
+native float3 Sample(Texture3D<float3>, sampler, float3 location, int3 offset);
+native float3 Sample(TextureCube<float3>, sampler, float3 location);
+native float4 Sample(Texture1D<float4>, sampler, float location);
+native float4 Sample(Texture1DArray<float4>, sampler, float2 location);
+native float4 Sample(Texture2D<float4>, sampler, float2 location);
+native float4 Sample(Texture2D<float4>, sampler, float2 location, int2 offset);
+native float4 Sample(Texture2DArray<float4>, sampler, float3 location);
+native float4 Sample(Texture2DArray<float4>, sampler, float3 location, int2 offset);
+native float4 Sample(Texture3D<float4>, sampler, float3 location);
+native float4 Sample(Texture3D<float4>, sampler, float3 location, int3 offset);
+native float4 Sample(TextureCube<float4>, sampler, float3 location);
+native float Sample(TextureDepth2D<float>, sampler, float2 location);
+native float Sample(TextureDepth2D<float>, sampler, float2 location, int2 offset);
+native float Sample(TextureDepth2DArray<float>, sampler, float3 location);
+native float Sample(TextureDepth2DArray<float>, sampler, float3 location, int2 offset);
+native float Sample(TextureDepthCube<float>, sampler, float3 location);
+
+native ushort Load(Texture1D<ushort>, int location);
+native ushort Load(Texture1DArray<ushort>, int2 location);
+native ushort Load(Texture2D<ushort>, int2 location);
+native ushort Load(Texture2DArray<ushort>, int3 location);
+native ushort Load(Texture3D<ushort>, int3 location);
+native ushort2 Load(Texture1D<ushort2>, int location);
+native ushort2 Load(Texture1DArray<ushort2>, int2 location);
+native ushort2 Load(Texture2D<ushort2>, int2 location);
+native ushort2 Load(Texture2DArray<ushort2>, int3 location);
+native ushort2 Load(Texture3D<ushort2>, int3 location);
+native ushort3 Load(Texture1D<ushort3>, int location);
+native ushort3 Load(Texture1DArray<ushort3>, int2 location);
+native ushort3 Load(Texture2D<ushort3>, int2 location);
+native ushort3 Load(Texture2DArray<ushort3>, int3 location);
+native ushort3 Load(Texture3D<ushort3>, int3 location);
+native ushort4 Load(Texture1D<ushort4>, int location);
+native ushort4 Load(Texture1DArray<ushort4>, int2 location);
+native ushort4 Load(Texture2D<ushort4>, int2 location);
+native ushort4 Load(Texture2DArray<ushort4>, int3 location);
+native ushort4 Load(Texture3D<ushort4>, int3 location);
+native uint Load(Texture1D<uint>, int location);
+native uint Load(Texture1DArray<uint>, int2 location);
+native uint Load(Texture2D<uint>, int2 location);
+native uint Load(Texture2DArray<uint>, int3 location);
+native uint Load(Texture3D<uint>, int3 location);
+native uint2 Load(Texture1D<uint2>, int location);
+native uint2 Load(Texture1DArray<uint2>, int2 location);
+native uint2 Load(Texture2D<uint2>, int2 location);
+native uint2 Load(Texture2DArray<uint2>, int3 location);
+native uint2 Load(Texture3D<uint2>, int3 location);
+native uint3 Load(Texture1D<uint3>, int location);
+native uint3 Load(Texture1DArray<uint3>, int2 location);
+native uint3 Load(Texture2D<uint3>, int2 location);
+native uint3 Load(Texture2DArray<uint3>, int3 location);
+native uint3 Load(Texture3D<uint3>, int3 location);
+native uint4 Load(Texture1D<uint4>, int location);
+native uint4 Load(Texture1DArray<uint4>, int2 location);
+native uint4 Load(Texture2D<uint4>, int2 location);
+native uint4 Load(Texture2DArray<uint4>, int3 location);
+native uint4 Load(Texture3D<uint4>, int3 location);
+native short Load(Texture1D<short>, int location);
+native short Load(Texture1DArray<short>, int2 location);
+native short Load(Texture2D<short>, int2 location);
+native short Load(Texture2DArray<short>, int3 location);
+native short Load(Texture3D<short>, int3 location);
+native short2 Load(Texture1D<short2>, int location);
+native short2 Load(Texture1DArray<short2>, int2 location);
+native short2 Load(Texture2D<short2>, int2 location);
+native short2 Load(Texture2DArray<short2>, int3 location);
+native short2 Load(Texture3D<short2>, int3 location);
+native short3 Load(Texture1D<short3>, int location);
+native short3 Load(Texture1DArray<short3>, int2 location);
+native short3 Load(Texture2D<short3>, int2 location);
+native short3 Load(Texture2DArray<short3>, int3 location);
+native short3 Load(Texture3D<short3>, int3 location);
+native short4 Load(Texture1D<short4>, int location);
+native short4 Load(Texture1DArray<short4>, int2 location);
+native short4 Load(Texture2D<short4>, int2 location);
+native short4 Load(Texture2DArray<short4>, int3 location);
+native short4 Load(Texture3D<short4>, int3 location);
+native int Load(Texture1D<int>, int location);
+native int Load(Texture1DArray<int>, int2 location);
+native int Load(Texture2D<int>, int2 location);
+native int Load(Texture2DArray<int>, int3 location);
+native int Load(Texture3D<int>, int3 location);
+native int2 Load(Texture1D<int2>, int location);
+native int2 Load(Texture1DArray<int2>, int2 location);
+native int2 Load(Texture2D<int2>, int2 location);
+native int2 Load(Texture2DArray<int2>, int3 location);
+native int2 Load(Texture3D<int2>, int3 location);
+native int3 Load(Texture1D<int3>, int location);
+native int3 Load(Texture1DArray<int3>, int2 location);
+native int3 Load(Texture2D<int3>, int2 location);
+native int3 Load(Texture2DArray<int3>, int3 location);
+native int3 Load(Texture3D<int3>, int3 location);
+native int4 Load(Texture1D<int4>, int location);
+native int4 Load(Texture1DArray<int4>, int2 location);
+native int4 Load(Texture2D<int4>, int2 location);
+native int4 Load(Texture2DArray<int4>, int3 location);
+native int4 Load(Texture3D<int4>, int3 location);
+native half Load(Texture1D<half>, int location);
+native half Load(Texture1DArray<half>, int2 location);
+native half Load(Texture2D<half>, int2 location);
+native half Load(Texture2DArray<half>, int3 location);
+native half Load(Texture3D<half>, int3 location);
+native half2 Load(Texture1D<half2>, int location);
+native half2 Load(Texture1DArray<half2>, int2 location);
+native half2 Load(Texture2D<half2>, int2 location);
+native half2 Load(Texture2DArray<half2>, int3 location);
+native half2 Load(Texture3D<half2>, int3 location);
+native half3 Load(Texture1D<half3>, int location);
+native half3 Load(Texture1DArray<half3>, int2 location);
+native half3 Load(Texture2D<half3>, int2 location);
+native half3 Load(Texture2DArray<half3>, int3 location);
+native half3 Load(Texture3D<half3>, int3 location);
+native half4 Load(Texture1D<half4>, int location);
+native half4 Load(Texture1DArray<half4>, int2 location);
+native half4 Load(Texture2D<half4>, int2 location);
+native half4 Load(Texture2DArray<half4>, int3 location);
+native half4 Load(Texture3D<half4>, int3 location);
+native float Load(Texture1D<float>, int location);
+native float Load(Texture1DArray<float>, int2 location);
+native float Load(Texture2D<float>, int2 location);
+native float Load(Texture2DArray<float>, int3 location);
+native float Load(Texture3D<float>, int3 location);
+native float2 Load(Texture1D<float2>, int location);
+native float2 Load(Texture1DArray<float2>, int2 location);
+native float2 Load(Texture2D<float2>, int2 location);
+native float2 Load(Texture2DArray<float2>, int3 location);
+native float2 Load(Texture3D<float2>, int3 location);
+native float3 Load(Texture1D<float3>, int location);
+native float3 Load(Texture1DArray<float3>, int2 location);
+native float3 Load(Texture2D<float3>, int2 location);
+native float3 Load(Texture2DArray<float3>, int3 location);
+native float3 Load(Texture3D<float3>, int3 location);
+native float4 Load(Texture1D<float4>, int location);
+native float4 Load(Texture1DArray<float4>, int2 location);
+native float4 Load(Texture2D<float4>, int2 location);
+native float4 Load(Texture2DArray<float4>, int3 location);
+native float4 Load(Texture3D<float4>, int3 location);
+native float Load(TextureDepth2D<float>, int2 location);
+native float Load(TextureDepth2DArray<float>, int3 location);
+
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, thread uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, thread uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, thread uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, device uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, device uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, device uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, threadgroup uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, threadgroup uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, thread uint* Width, threadgroup uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, thread uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, thread uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, thread uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, device uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, device uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, device uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, threadgroup uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, threadgroup uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, device uint* Width, threadgroup uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, thread uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, thread uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, thread uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, device uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, device uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, device uint* Height, threadgroup uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, threadgroup uint* Height, thread uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, threadgroup uint* Height, device uint* NumberOfLevels);
+native void GetDimensions(Texture2D<float4>, uint MipLevel, threadgroup uint* Width, threadgroup uint* Height, threadgroup uint* NumberOfLevels);
+
 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=192890 Insert the rest of the standard library once the parser is fast enough
index 9cb5c81..b584b9e 100644 (file)
@@ -39,7 +39,7 @@ namespace WHLSL {
 
 class FindArrayTypes : public Visitor {
 public:
-    ~FindArrayTypes() = default;
+    virtual ~FindArrayTypes() = default;
 
     void visit(AST::ArrayType& arrayType) override
     {
index 84b2d4e..c522ea7 100644 (file)
@@ -82,7 +82,7 @@ private:
 
 class FindAllTypes : public Visitor {
 public:
-    ~FindAllTypes() = default;
+    virtual ~FindAllTypes() = default;
 
     void visit(AST::PointerType& pointerType) override
     {
@@ -171,7 +171,7 @@ bool synthesizeConstructors(Program& program)
     for (auto& namedType : namedTypes) {
         if (matches(namedType, program.intrinsics().voidType()))
             continue;
-        if (is<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)) && downcast<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)).isAtom())
+        if (is<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)) && downcast<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType)).isAtomic())
             continue;
 
         auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(namedType.get().origin()), AST::Qualifiers(), UniqueRef<AST::UnnamedType>(AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get())), String(), WTF::nullopt, WTF::nullopt);
@@ -180,6 +180,11 @@ bool synthesizeConstructors(Program& program)
         AST::NativeFunctionDeclaration copyConstructor(AST::FunctionDeclaration(Lexer::Token(namedType.get().origin()), AST::AttributeBlock(), WTF::nullopt, AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get()), "operator cast"_str, WTFMove(parameters), WTF::nullopt, isOperator));
         program.append(WTFMove(copyConstructor));
 
+        if (is<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType))) {
+            auto& nativeTypeDeclaration = downcast<AST::NativeTypeDeclaration>(static_cast<AST::NamedType&>(namedType));
+            if (nativeTypeDeclaration.isOpaqueType())
+                continue;
+        }
         AST::NativeFunctionDeclaration defaultConstructor(AST::FunctionDeclaration(Lexer::Token(namedType.get().origin()), AST::AttributeBlock(), WTF::nullopt, AST::TypeReference::wrap(Lexer::Token(namedType.get().origin()), namedType.get()), "operator cast"_str, AST::VariableDeclarations(), WTF::nullopt, isOperator));
         if (!program.append(WTFMove(defaultConstructor)))
             return false;
index ded889a..de833de 100644 (file)
@@ -312,6 +312,7 @@ Modules/webgpu/WHLSL/WHLSLAutoInitializeVariables.cpp
 Modules/webgpu/WHLSL/WHLSLInferTypes.cpp
 Modules/webgpu/WHLSL/WHLSLLexer.cpp
 Modules/webgpu/WHLSL/WHLSLParser.cpp
+Modules/webgpu/WHLSL/WHLSLCheckTextureReferences.cpp
 Modules/webgpu/WHLSL/WHLSLChecker.cpp
 Modules/webgpu/WHLSL/WHLSLGatherEntryPointItems.cpp
 Modules/webgpu/WHLSL/WHLSLCheckDuplicateFunctions.cpp
index 684af84..bc08b6f 100644 (file)
                1C24EEA61C72A7B40080F8FC /* JSFontFaceSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSFontFaceSet.cpp; path = DerivedSources/WebCore/JSFontFaceSet.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
                1C24EEA71C72A7B40080F8FC /* JSFontFaceSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSFontFaceSet.h; path = DerivedSources/WebCore/JSFontFaceSet.h; sourceTree = BUILT_PRODUCTS_DIR; };
                1C2649790D7E248A00BD10F2 /* DocumentLoaderMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentLoaderMac.cpp; sourceTree = "<group>"; };
+               1C281C6D22B87B9800691C00 /* WHLSLCheckTextureReferences.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLCheckTextureReferences.cpp; sourceTree = "<group>"; };
+               1C281C6E22B87B9800691C00 /* WHLSLCheckTextureReferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLCheckTextureReferences.h; sourceTree = "<group>"; };
                1C3249101C6D6A3B007EDB32 /* FontVariantBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontVariantBuilder.cpp; sourceTree = "<group>"; };
                1C33277121CF0BE1000DC9F2 /* WHLSLNamedType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNamedType.h; sourceTree = "<group>"; };
                1C33277221CF0D2E000DC9F2 /* WHLSLUnnamedType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLUnnamedType.h; sourceTree = "<group>"; };
                                C234A9AE21E92C1A003C984D /* WHLSLCheckDuplicateFunctions.h */,
                                1C840B9B21EC400900D0500D /* WHLSLChecker.cpp */,
                                1C840B9721EC400700D0500D /* WHLSLChecker.h */,
+                               1C281C6D22B87B9800691C00 /* WHLSLCheckTextureReferences.cpp */,
+                               1C281C6E22B87B9800691C00 /* WHLSLCheckTextureReferences.h */,
                                1C86CA4B22AA19FF001BF961 /* WHLSLComputeDimensions.cpp */,
                                1C86CA4C22AA19FF001BF961 /* WHLSLComputeDimensions.h */,
                                1CA0C2E421EED12A00A11860 /* WHLSLFunctionStageChecker.cpp */,
index d11bfcc..61912af 100644 (file)
@@ -54,6 +54,8 @@ public:
     bool isTransferDestination() const { return m_usage.contains(GPUTextureUsage::Flags::TransferDestination); }
     bool isOutputAttachment() const { return m_usage.contains(GPUTextureUsage::Flags::OutputAttachment); }
     bool isReadOnly() const { return m_usage.containsAny({ GPUTextureUsage::Flags::TransferSource, GPUTextureUsage::Flags::Sampled }); }
+    bool isSampled() const { return m_usage.contains(GPUTextureUsage::Flags::Sampled); }
+    bool isStorage() const { return m_usage.contains(GPUTextureUsage::Flags::Storage); }
 
     RefPtr<GPUTexture> tryCreateDefaultTextureView();
     void destroy() { m_platformTexture = nullptr; }
index 6262e5f..3e0c7d3 100644 (file)
@@ -216,22 +216,22 @@ RefPtr<GPUBindGroup> GPUBindGroup::tryCreate(const GPUBindGroupDescriptor& descr
             if (!samplerState)
                 return false;
             if (isForVertex)
-                setSamplerOnEncoder(vertexEncoder, samplerState, index);
+                setSamplerOnEncoder(vertexEncoder, samplerState, layoutBinding.internalName);
             if (isForFragment)
-                setSamplerOnEncoder(fragmentEncoder, samplerState, index);
+                setSamplerOnEncoder(fragmentEncoder, samplerState, layoutBinding.internalName);
             if (isForCompute)
-                setSamplerOnEncoder(computeEncoder, samplerState, index);
+                setSamplerOnEncoder(computeEncoder, samplerState, layoutBinding.internalName);
             return true;
         }, [&](GPUBindGroupLayout::SampledTexture&) -> bool {
             auto textureResource = tryGetResourceAsTexture(resourceBinding.resource, functionName);
             if (!textureResource)
                 return false;
             if (isForVertex)
-                setTextureOnEncoder(vertexEncoder, textureResource->platformTexture(), index);
+                setTextureOnEncoder(vertexEncoder, textureResource->platformTexture(), layoutBinding.internalName);
             if (isForFragment)
-                setTextureOnEncoder(fragmentEncoder, textureResource->platformTexture(), index);
+                setTextureOnEncoder(fragmentEncoder, textureResource->platformTexture(), layoutBinding.internalName);
             if (isForCompute)
-                setTextureOnEncoder(computeEncoder, textureResource->platformTexture(), index);
+                setTextureOnEncoder(computeEncoder, textureResource->platformTexture(), layoutBinding.internalName);
             boundTextures.append(textureResource.releaseNonNull());
             return true;
         }, [&](GPUBindGroupLayout::StorageBuffer& storageBuffer) -> bool {
index 2e98718..62e1158 100644 (file)
@@ -63,11 +63,27 @@ void GPUProgrammablePassEncoder::setBindGroup(unsigned index, GPUBindGroup& bind
         setComputeBuffer(bindGroup.computeArgsBuffer(), 0, index);
 
     for (auto& bufferRef : bindGroup.boundBuffers()) {
-        useResource(bufferRef->platformBuffer(), bufferRef->isReadOnly() ? MTLResourceUsageRead : MTLResourceUsageRead | MTLResourceUsageWrite);
+        MTLResourceUsage usage = 0;
+        if (bufferRef->isUniform()) {
+            ASSERT(!bufferRef->isStorage());
+            usage = MTLResourceUsageRead;
+        } else if (bufferRef->isStorage()) {
+            ASSERT(!bufferRef->isUniform());
+            usage = MTLResourceUsageRead | MTLResourceUsageWrite;
+        }
+        useResource(bufferRef->platformBuffer(), usage);
         m_commandBuffer->useBuffer(bufferRef.copyRef());
     }
     for (auto& textureRef : bindGroup.boundTextures()) {
-        useResource(textureRef->platformTexture(), textureRef->isReadOnly() ? MTLResourceUsageRead : MTLResourceUsageRead | MTLResourceUsageWrite);
+        MTLResourceUsage usage = 0;
+        if (textureRef->isSampled()) {
+            ASSERT(!textureRef->isStorage());
+            usage = MTLResourceUsageRead | MTLResourceUsageSample;
+        } else if (textureRef->isStorage()) {
+            ASSERT(!textureRef->isSampled());
+            usage = MTLResourceUsageRead | MTLResourceUsageWrite;
+        }
+        useResource(textureRef->platformTexture(), usage);
         m_commandBuffer->useTexture(textureRef.copyRef());
     }
 }
index 783c013..ee48928 100644 (file)
@@ -59,27 +59,26 @@ static Optional<MTLTextureUsage> mtlTextureUsageForGPUTextureUsageFlags(OptionSe
 #if LOG_DISABLED
     UNUSED_PARAM(functionName);
 #endif
+
     if (flags.containsAny({ GPUTextureUsage::Flags::TransferSource, GPUTextureUsage::Flags::Sampled }) && (flags & GPUTextureUsage::Flags::Storage)) {
         LOG(WebGPU, "%s: Texture cannot have both STORAGE and a read-only usage!", functionName);
         return WTF::nullopt;
     }
 
-    if (flags & GPUTextureUsage::Flags::OutputAttachment) {
-        if (flags.containsAny({ GPUTextureUsage::Flags::Storage, GPUTextureUsage::Flags::Sampled })) {
-            LOG(WebGPU, "%s: Texture cannot have OUTPUT_ATTACHMENT usage with STORAGE or SAMPLED usages!", functionName);
-            return WTF::nullopt;
-        }
-
-        return MTLTextureUsageRenderTarget | MTLTextureUsagePixelFormatView;
+    if (flags & GPUTextureUsage::Flags::OutputAttachment && flags.containsAny({ GPUTextureUsage::Flags::Storage, GPUTextureUsage::Flags::Sampled })) {
+        LOG(WebGPU, "%s: Texture cannot have OUTPUT_ATTACHMENT usage with STORAGE or SAMPLED usages!", functionName);
+        return WTF::nullopt;
     }
 
-    if (flags & GPUTextureUsage::Flags::Storage)
-        return MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead | MTLTextureUsagePixelFormatView;
-
-    if (flags & GPUTextureUsage::Flags::Sampled)
-        return MTLTextureUsageShaderRead | MTLTextureUsagePixelFormatView;
+    MTLTextureUsage result = MTLTextureUsagePixelFormatView;
+    if (flags.contains(GPUTextureUsage::Flags::OutputAttachment))
+        result |= MTLTextureUsageRenderTarget;
+    if (flags.containsAny({ GPUTextureUsage::Flags::Storage, GPUTextureUsage::Flags::Sampled }))
+        result |= MTLTextureUsageShaderRead;
+    if (flags.contains(GPUTextureUsage::Flags::Storage))
+        result |= MTLTextureUsageShaderWrite;
 
-    return MTLTextureUsageUnknown;
+    return result;
 }
 
 #if !PLATFORM(MAC)