Diff
Modified: trunk/LayoutTests/ChangeLog (241995 => 241996)
--- trunk/LayoutTests/ChangeLog 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/ChangeLog 2019-02-23 23:24:27 UTC (rev 241996)
@@ -1,3 +1,23 @@
+2019-02-23 Justin Fan <justin_...@apple.com>
+
+ [WebGPU] Buffer updates part 1: async mapping functions, unmap, and destroy
+ https://bugs.webkit.org/show_bug.cgi?id=194665
+
+ Reviewed by Dean Jackson.
+
+ Rewrite buffers.html -> map-write-buffers.html to test new functionality. Rewrite other affected
+ tests to use mapWriteAsync.
+
+ * webgpu/buffer-resource-triangles.html:
+ * webgpu/buffers-expected.txt: Renamed to map-write-buffers-expected.txt.
+ * webgpu/buffers.html: Renamed to map-write-buffers.html.
+ * webgpu/depth-enabled-triangle-strip.html:
+ * webgpu/map-write-buffers-expected.txt: Renamed from buffers-expected.txt.
+ * webgpu/map-write-buffers.html: Renamed from buffers.html.
+ * webgpu/vertex-buffer-triangle-strip.html:
+
+ * platform/mac/TestExpectations: Skip all webgpu tests on macOS 10.12 bots.
+
2019-02-23 chris fleizach <cfleiz...@apple.com>
AX: WebKit is incorrectly mapping the <meter> element to progressbar
Modified: trunk/LayoutTests/platform/mac/TestExpectations (241995 => 241996)
--- trunk/LayoutTests/platform/mac/TestExpectations 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2019-02-23 23:24:27 UTC (rev 241996)
@@ -1785,18 +1785,6 @@
webkit.org/b/190976 imported/w3c/web-platform-tests/media-source/mediasource-changetype-play.html [ Pass Failure ]
-webkit.org/b/192956 [ Sierra ] webgpu/buffers.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/command-buffers.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/pipeline-layouts.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/queue-creation.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/render-command-encoding.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/render-passes.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/render-pipelines.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/shader-modules.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/textures-textureviews.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/webgpu-basics.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/webgpu-enabled.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/simple-triangle-strip.html [ Skip ]
-webkit.org/b/192956 [ Sierra ] webgpu/vertex-buffer-triangle-strip.html [ Skip ]
+webkit.org/b/192956 [ Sierra ] webgpu [ Skip ]
webkit.org/b/189680 platform/mac/media/audio-session-category-video-paused.html [ Pass Timeout ]
Modified: trunk/LayoutTests/webgpu/buffer-resource-triangles.html (241995 => 241996)
--- trunk/LayoutTests/webgpu/buffer-resource-triangles.html 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/webgpu/buffer-resource-triangles.html 2019-02-23 23:24:27 UTC (rev 241996)
@@ -79,34 +79,33 @@
const vertexSize = 4 * 4;
const verticesBufferSize = vertexSize * 3;
+function createAndUploadVerticesBuffer(device, promises) {
+ const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE });
-// FIXME: Keep up to date with buffer upload decisions.
-function createVerticesBuffer(device) {
- const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX });
+ const promise = buffer.mapWriteAsync().then(mapping => {
+ const mappedArray = new Float32Array(mapping);
+ mappedArray.set([
+ 0, 1, 0, 1,
+ -1, -1, 0, 1,
+ 1, -1, 0, 1
+ ]);
+ buffer.unmap();
+ });
- const vertices = [
- 0, 1, 0, 1,
- -1, -1, 0, 1,
- 1, -1, 0, 1
- ];
-
- const mappedArray = new Float32Array(buffer.mapping);
- mappedArray.set(vertices);
-
+ promises.push(promise);
return buffer;
}
-function createFloat4Buffer(device, a, b) {
- const buffer = device.createBuffer({ size: vertexSize, usage: GPUBufferUsage.UNIFORM });
-
- const arrayBuffer = buffer.mapping;
- const floatArray = new Float32Array(arrayBuffer);
+function createFloat4Buffer(device, a, b, promises) {
+ const buffer = device.createBuffer({ size: vertexSize, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE });
- floatArray[0] = a;
- floatArray[1] = b;
- floatArray[2] = 0;
- floatArray[3] = 1;
+ const promise = buffer.mapWriteAsync().then(mapping => {
+ const mappedArray = new Float32Array(mapping);
+ mappedArray.set([a, b, 0, 1]);
+ buffer.unmap();
+ });
+ promises.push(promise);
return buffer;
}
@@ -126,16 +125,18 @@
const shaderModule = device.createShaderModule({ code: shaderCode });
// Create vertex data WebGPUBuffers.
- const verticesBuffer = createVerticesBuffer(device);
+ let bufferPromises = [];
- const upperLeft = createFloat4Buffer(device, -1, 1);
- const upperMiddle = createFloat4Buffer(device, 0, 1);
- const upperRight = createFloat4Buffer(device, 1, 1);
- const lowerLeft = createFloat4Buffer(device, -1, -1);
- const lowerRight = createFloat4Buffer(device, 1, -1);
+ const verticesBuffer = createAndUploadVerticesBuffer(device, bufferPromises);
+ const upperLeft = createFloat4Buffer(device, -1, 1, bufferPromises);
+ const upperMiddle = createFloat4Buffer(device, 0, 1, bufferPromises);
+ const upperRight = createFloat4Buffer(device, 1, 1, bufferPromises);
+ const lowerLeft = createFloat4Buffer(device, -1, -1, bufferPromises);
+ const lowerRight = createFloat4Buffer(device, 1, -1, bufferPromises);
+
// Color data buffer.
- const green = createFloat4Buffer(device, 0, 1);
+ const green = createFloat4Buffer(device, 0, 1, bufferPromises);
// Create vertex input state.
const inputState = {
@@ -195,21 +196,23 @@
bindings: [bgBindingUR, bgBindingUM, bgBindingLR]
});
- const commandBuffer = device.createCommandBuffer();
- const passEncoder = beginBasicRenderPass(context, commandBuffer);
- passEncoder.setPipeline(pipeline);
+ Promise.all(bufferPromises).then(() => {
+ const commandBuffer = device.createCommandBuffer();
+ const passEncoder = beginBasicRenderPass(context, commandBuffer);
+ passEncoder.setPipeline(pipeline);
- // Vertex data for upper triangles.
- passEncoder.setBindGroup(0, leftTriangleBG);
- passEncoder.setBindGroup(1, rightTriangleBG);
- // Lower triangle.
- passEncoder.setVertexBuffers(0, [verticesBuffer], [0]);
- passEncoder.draw(9, 1, 0, 0);
+ // Vertex data for upper triangles.
+ passEncoder.setBindGroup(0, leftTriangleBG);
+ passEncoder.setBindGroup(1, rightTriangleBG);
+ // Lower triangle.
+ passEncoder.setVertexBuffers(0, [verticesBuffer], [0]);
+ passEncoder.draw(9, 1, 0, 0);
- const endCommandBuffer = passEncoder.endPass();
- const queue = device.getQueue();
- queue.submit([endCommandBuffer]);
- context.present();
+ const endCommandBuffer = passEncoder.endPass();
+ const queue = device.getQueue();
+ queue.submit([endCommandBuffer]);
+ context.present();
+ });
}
test();
Deleted: trunk/LayoutTests/webgpu/buffers-expected.txt (241995 => 241996)
--- trunk/LayoutTests/webgpu/buffers-expected.txt 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/webgpu/buffers-expected.txt 2019-02-23 23:24:27 UTC (rev 241996)
@@ -1,4 +0,0 @@
-PASS [object WebGPU] is defined.
-
-PASS createBuffer() on WebGPUDevice.
-
Deleted: trunk/LayoutTests/webgpu/buffers.html (241995 => 241996)
--- trunk/LayoutTests/webgpu/buffers.html 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/webgpu/buffers.html 2019-02-23 23:24:27 UTC (rev 241996)
@@ -1,31 +0,0 @@
-<!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] -->
-<meta charset=utf-8>
-<title>Get the WebGPUDevice, create a WebGPUBuffer, and write vertex data to it.</title>
-<body>
-<script src=""
-<script src=""
-<script src=""
-<script src=""
-<script>
-function createBuffer() {
- const buffer = defaultDevice.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_WRITE });
- assert_true(buffer instanceof WebGPUBuffer, "createBuffer returned a WebGPUBuffer");
-
- let arrayBuffer = buffer.mapping;
- let floatArray = new Float32Array(arrayBuffer);
- assert_equals(floatArray.length, 4);
-
- floatArray[0] = -1;
- floatArray[1] = 1;
- floatArray[2] = 0;
- floatArray[3] = 1;
-}
-
-promise_test(async t => {
- const canvas = document.createElement("canvas");
- await setUpContexts(canvas);
- createBuffer();
-}, "createBuffer() on WebGPUDevice.");
-
-</script>
-</body>
Modified: trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html (241995 => 241996)
--- trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html 2019-02-23 23:24:27 UTC (rev 241996)
@@ -44,22 +44,23 @@
}
`
-function createVertexBuffer(device) {
+async function createVertexBuffer(device) {
const bufferSize = 4 * 4 * 4;
- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.MAP_WRITE });
+ const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE });
let floatArray = new Float32Array(buffer.mapping);
+ await buffer.mapWriteAsync().then(mapping => {
+ let mappedArray = new Float32Array(mapping);
+ mappedArray.set([
+ // float4 xyzw
+ -1, 1, 0, 1,
+ -1, -1, 0, 1,
+ 1, 1, 0, 1,
+ 1, -1, 0, 1
+ ]);
+ buffer.unmap();
+ });
- const vertices = [
- // float4 xyzw
- -1, 1, 0, 1,
- -1, -1, 0, 1,
- 1, 1, 0, 1,
- 1, -1, 0, 1
- ];
-
- floatArray.set(vertices);
-
return buffer;
}
@@ -86,7 +87,7 @@
const context = createBasicContext(canvas, device);
// FIXME: Replace with non-MSL shaders.
const shaderModule = device.createShaderModule({ code: shaderCode });
- const vertexBuffer = createVertexBuffer(device);
+ const vertexBuffer = await createVertexBuffer(device);
const inputStateDescriptor = createInputStateDescriptor();
const depthStateDescriptor = createBasicDepthStateDescriptor();
const pipeline = createBasicPipeline(shaderModule, device, null, inputStateDescriptor, depthStateDescriptor);
Added: trunk/LayoutTests/webgpu/map-write-buffers-expected.txt (0 => 241996)
--- trunk/LayoutTests/webgpu/map-write-buffers-expected.txt (rev 0)
+++ trunk/LayoutTests/webgpu/map-write-buffers-expected.txt 2019-02-23 23:24:27 UTC (rev 241996)
@@ -0,0 +1,6 @@
+
+PASS Map write, unmap, and destroy a GPUBuffer.
+PASS Reject a map write on a buffer not created with MAP_WRITE usage.
+PASS Reject a map write on a mapped GPUBuffer.
+PASS Reject a pending map write if GPUBuffer is unmapped.
+
Added: trunk/LayoutTests/webgpu/map-write-buffers.html (0 => 241996)
--- trunk/LayoutTests/webgpu/map-write-buffers.html (rev 0)
+++ trunk/LayoutTests/webgpu/map-write-buffers.html 2019-02-23 23:24:27 UTC (rev 241996)
@@ -0,0 +1,78 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] -->
+<meta charset=utf-8>
+<title>Tests for mapWriteAsync on a GPUBuffer.</title>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script>
+async function runTests() {
+ const device = await getBasicDevice();
+
+ // Basic mapWriteAsync functionality
+ promise_test(async () => {
+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_WRITE });
+ assert_true(buffer instanceof WebGPUBuffer, "createBuffer returned a WebGPUBuffer");
+
+ let arrayBuffer = await buffer.mapWriteAsync();
+
+ assert_true(arrayBuffer instanceof ArrayBuffer, "first mapWriteAsync resolved successfully");
+
+ let array = new Float32Array(arrayBuffer);
+ assert_equals(array[0], 0, "mapWriteAsync zeroed out storage");
+ array.set([1, 2, 3, 4]);
+
+ buffer.unmap();
+
+ const promise = buffer.mapWriteAsync(); // This will eventually reject due to buffer.destroy()
+
+ buffer.destroy();
+
+ await promise.then(() => {
+ assert_unreached("Buffer was destroyed!");
+ }, () => {});
+
+ }, "Map write, unmap, and destroy a GPUBuffer.");
+
+ /* Basic validation */
+ // FIXME: Test invalid combinations of GPUBufferUsage after implementing error handling.
+
+ promise_test(async () => {
+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ });
+
+ await buffer.mapWriteAsync().then(() => {
+ assert_unreached("Buffer was not created with MAP_WRITE!");
+ }, () => {});
+ }, "Reject a map write on a buffer not created with MAP_WRITE usage.");
+
+ /* Extended unmap/destroy and promise settling testing */
+
+ promise_test(async () => {
+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_WRITE });
+
+ buffer.mapWriteAsync().then(() => {
+ buffer.unmap();
+ }, () => {
+ assert_unreached();
+ });
+
+ await buffer.mapWriteAsync().then(() => {
+ assert_unreached("Map operation was invalid!"); // buffer was still in mapped state during promise creation
+ }, () => {});
+ }, "Reject a map write on a mapped GPUBuffer.");
+
+ promise_test(async () => {
+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_WRITE });
+
+ const promise = buffer.mapWriteAsync();
+ buffer.unmap();
+
+ await promise.then(() => {
+ assert_unreached("Buffer was unmapped!"); // buffer was unmapped, which rejects pending promises
+ },() => {});
+ }, "Reject a pending map write if GPUBuffer is unmapped.");
+}
+
+runTests();
+</script>
+</body>
Modified: trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html (241995 => 241996)
--- trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html 2019-02-23 23:24:27 UTC (rev 241996)
@@ -38,24 +38,22 @@
}
`
-function createVertexBuffer(device) {
+async function createVertexBuffer(device) {
const bufferSize = 4 * 5 * 4;
- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.MAP_WRITE });
+ const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE });
- let floatArray = new Float32Array(buffer.mapping);
+ await buffer.mapWriteAsync().then(mapping => {
+ let mappedArray = new Float32Array(mapping);
+ mappedArray.set([
+ // float4 xyzw, float g
+ -1, 1, 0, 1, 1,
+ -1, -1, 0, 1, 1,
+ 1, 1, 0, 1, 1,
+ 1, -1, 0, 1, 1
+ ]);
+ buffer.unmap();
+ });
- const vertices = [
- // float4 xyzw, float g
- -1, 1, 0, 1, 1,
- -1, -1, 0, 1, 1,
- 1, 1, 0, 1, 1,
- 1, -1, 0, 1, 1
- ];
-
- for (let i = 0; i < vertices.length; ++i) {
- floatArray[i] = vertices[i];
- }
-
return buffer;
}
@@ -87,7 +85,7 @@
const context = createBasicContext(canvas, device);
// FIXME: Replace with non-MSL shaders.
const shaderModule = device.createShaderModule({ code: shaderCode });
- const vertexBuffer = createVertexBuffer(device);
+ const vertexBuffer = await createVertexBuffer(device);
const inputStateDescriptor = createInputStateDescriptor();
const pipeline = createBasicPipeline(shaderModule, device, null, inputStateDescriptor);
const commandBuffer = device.createCommandBuffer();
Modified: trunk/Source/WebCore/ChangeLog (241995 => 241996)
--- trunk/Source/WebCore/ChangeLog 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/ChangeLog 2019-02-23 23:24:27 UTC (rev 241996)
@@ -1,3 +1,73 @@
+2019-02-23 Justin Fan <justin_...@apple.com>
+
+ [WebGPU] Buffer updates part 1: async mapping functions, unmap, and destroy
+ https://bugs.webkit.org/show_bug.cgi?id=194665
+
+ Reviewed by Dean Jackson.
+
+ Test: map-write-buffers.html. Other tests updated to match new API.
+
+ * Modules/webgpu/WebGPUBindGroupDescriptor.cpp: Added.
+ (WebCore::validateBufferBindingType): Ensure buffer binding usages match the binding type.
+ (WebCore::WebGPUBindGroupDescriptor::asGPUBindGroupDescriptor const): Logic moved out from WebGPUDevice.cpp.
+ * Modules/webgpu/WebGPUBindGroupDescriptor.h:
+ * Modules/webgpu/WebGPUBuffer.cpp: Added GPUBuffer functionality.
+ (WebCore::WebGPUBuffer::create):
+ (WebCore::WebGPUBuffer::WebGPUBuffer):
+ (WebCore::WebGPUBuffer::mapReadAsync):
+ (WebCore::WebGPUBuffer::mapWriteAsync):
+ (WebCore::WebGPUBuffer::unmap):
+ (WebCore::WebGPUBuffer::destroy):
+ (WebCore::WebGPUBuffer::rejectOrRegisterPromiseCallback): Register a mapping request on the GPUBuffer, if valid.
+ * Modules/webgpu/WebGPUBuffer.h:
+ (WebCore::WebGPUBuffer::buffer const):
+ (WebCore::WebGPUBuffer::mapping const): Deleted.
+ * Modules/webgpu/WebGPUBuffer.idl: Update to latest API and enable every function except setSubData.
+ * Modules/webgpu/WebGPUCommandBuffer.cpp:
+ (WebCore::WebGPUCommandBuffer::beginRenderPass): Renamed descriptor conversion method.
+ * Modules/webgpu/WebGPUDevice.cpp:
+ (WebCore::WebGPUDevice::createBuffer const): Update to non-nullable return type.
+ (WebCore::WebGPUDevice::createBindGroup const): Move descriptor validation logic to descriptor implementation.
+ * Modules/webgpu/WebGPUDevice.h:
+ * Modules/webgpu/WebGPURenderPassDescriptor.cpp:
+ (WebCore::WebGPURenderPassDescriptor::asGPURenderPassDescriptor const): Renamed from validateAndConvertToGPUVersion.
+ * Modules/webgpu/WebGPURenderPassEncoder.cpp:
+ (WebCore::WebGPURenderPassEncoder::setVertexBuffers): Add validation for submitted buffers.
+ * platform/graphics/gpu/GPUBuffer.cpp: Added.
+ (WebCore::GPUBuffer::PendingMappingCallback::PendingMappingCallback): New struct for retaining a reference to mapping callbacks.
+ * platform/graphics/gpu/GPUBuffer.h: Add functionality to retain callbacks and usage bits.
+ (WebCore::GPUBuffer::isVertex const):
+ (WebCore::GPUBuffer::isUniform const):
+ (WebCore::GPUBuffer::isStorage const):
+ (WebCore::GPUBuffer::isReadOnly const):
+ (WebCore::GPUBuffer::PendingMapPromise::create):
+ (WebCore::GPUBuffer::isMappable const):
+ (WebCore::GPUBuffer::isMapWriteable const):
+ (WebCore::GPUBuffer::isMapReadable const):
+ (WebCore::GPUBuffer::mapping const): Deleted.
+ * platform/graphics/gpu/GPUBufferUsage.h: enum class cannot be logical ORed together.
+ * platform/graphics/gpu/GPUDevice.cpp:
+ (WebCore::GPUDevice::tryCreateBuffer const): Renamed from createBuffer.
+ (WebCore::GPUDevice::createBuffer const): Deleted.
+ * platform/graphics/gpu/GPUDevice.h:
+ * platform/graphics/gpu/cocoa/GPUBufferMetal.mm:
+ (WebCore::GPUBuffer::tryCreateSharedBuffer): Attempt to create a MTLBuffer with shared memory.
+ (WebCore::GPUBuffer::tryCreate): No longer use Gigacage-allocated memory for MTLBuffer.
+ (WebCore::GPUBuffer::GPUBuffer):
+ (WebCore::GPUBuffer::~GPUBuffer):
+ (WebCore::GPUBuffer::registerMappingCallback): Register the provided callback to be executed when the staging buffer can be safely exposed.
+ (WebCore::GPUBuffer::stagingBufferForRead): Prepare the arrayBuffer for reading and run the mapping callback.
+ (WebCore::GPUBuffer::stagingBufferForWrite): Ditto, but for writing.
+ (WebCore::GPUBuffer::unmap): If needed, copy the staging ArrayBuffer to the MTLBuffer. Unregister any mapping callback.
+ (WebCore::GPUBuffer::destroy): Stub implementation for now. Frees the MTLBuffer as soon as possible.
+ (WebCore::GPUBuffer::create): Deleted.
+ * platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm:
+ (WebCore::GPUProgrammablePassEncoder::setResourceAsBufferOnEncoder): Ensure only read-only GPUBuffers are used as read-only on the GPU.
+
+ Add symbols for new files:
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+
2019-02-23 Keith Miller <keith_mil...@apple.com>
Add new mac target numbers
Added: trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp (0 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -0,0 +1,120 @@
+/*
+ * 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 "WebGPUBindGroupDescriptor.h"
+
+#if ENABLE(WEBGPU)
+
+#include "GPUBindGroupDescriptor.h"
+#include "GPUBuffer.h"
+#include "Logging.h"
+#include <wtf/Variant.h>
+
+namespace WebCore {
+
+static bool validateBufferBindingType(const GPUBuffer* buffer, const GPUBindGroupLayoutBinding& binding, const char* const functionName)
+{
+#if LOG_DISABLED
+ UNUSED_PARAM(functionName);
+#endif
+
+ switch (binding.type) {
+ case GPUBindGroupLayoutBinding::BindingType::UniformBuffer:
+ if (!buffer->isUniform()) {
+ LOG(WebGPU, "%s: GPUBuffer resource for binding %lu does not have UNIFORM usage!", functionName, binding.binding);
+ return false;
+ }
+ return true;
+ case GPUBindGroupLayoutBinding::BindingType::StorageBuffer:
+ if (!buffer->isStorage()) {
+ LOG(WebGPU, "%s: GPUBuffer resource for binding %lu does not have STORAGE usage!", functionName, binding.binding);
+ return false;
+ }
+ return true;
+ default:
+ LOG(WebGPU, "%s: Layout binding %lu is not a buffer-type resource!", functionName, binding.binding);
+ return false;
+ }
+}
+
+Optional<GPUBindGroupDescriptor> WebGPUBindGroupDescriptor::asGPUBindGroupDescriptor() const
+{
+ const char* const functionName = "GPUDevice::createBindGroup()";
+
+ if (!layout || !layout->bindGroupLayout()) {
+ LOG(WebGPU, "%s: Invalid GPUBindGroupLayout!", functionName);
+ return WTF::nullopt;
+ }
+
+ if (bindings.size() != layout->bindGroupLayout()->bindingsMap().size()) {
+ LOG(WebGPU, "%s: Mismatched number of GPUBindGroupLayoutBindings and GPUBindGroupBindings!", functionName);
+ return WTF::nullopt;
+ }
+
+ auto layoutMap = layout->bindGroupLayout()->bindingsMap();
+
+ Vector<GPUBindGroupBinding> bindGroupBindings;
+ bindGroupBindings.reserveCapacity(bindings.size());
+
+ for (const auto& binding : bindings) {
+ auto iterator = layoutMap.find(binding.binding);
+ if (iterator == layoutMap.end()) {
+ LOG(WebGPU, "%s: GPUBindGroupLayoutBinding %lu not found in GPUBindGroupLayout!", functionName, binding.binding);
+ return WTF::nullopt;
+ }
+
+ auto layoutBinding = iterator->value;
+
+ auto bindingResourceVisitor = WTF::makeVisitor([] (RefPtr<WebGPUTextureView> view) -> Optional<GPUBindingResource> {
+ // FIXME: Validate binding type with the texture's usage flags.
+ if (!view)
+ return WTF::nullopt;
+
+ return static_cast<GPUBindingResource>(view->texture());
+ }, [&layoutBinding, functionName] (const WebGPUBufferBinding& binding) -> Optional<GPUBindingResource> {
+ if (!binding.buffer || !binding.buffer->buffer()) {
+ LOG(WebGPU, "%s: Invalid GPUBufferBinding for binding %lu in GPUBindGroupBindings!", functionName, layoutBinding.binding);
+ return WTF::nullopt;
+ }
+ if (!validateBufferBindingType(binding.buffer->buffer().get(), layoutBinding, functionName))
+ return WTF::nullopt;
+
+ return static_cast<GPUBindingResource>(GPUBufferBinding { binding.buffer->buffer().releaseNonNull(), binding.offset, binding.size });
+ });
+
+ auto bindingResource = WTF::visit(bindingResourceVisitor, binding.resource);
+ if (!bindingResource)
+ return WTF::nullopt;
+
+ bindGroupBindings.uncheckedAppend(GPUBindGroupBinding { binding.binding, WTFMove(bindingResource.value()) });
+ }
+
+ return GPUBindGroupDescriptor { layout->bindGroupLayout().releaseNonNull(), WTFMove(bindGroupBindings) };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.h (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -29,12 +29,17 @@
#include "WebGPUBindGroupBinding.h"
#include "WebGPUBindGroupLayout.h"
+#include <wtf/Optional.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
+struct GPUBindGroupDescriptor;
+
struct WebGPUBindGroupDescriptor {
+ Optional<GPUBindGroupDescriptor> asGPUBindGroupDescriptor() const;
+
RefPtr<WebGPUBindGroupLayout> layout;
Vector<WebGPUBindGroupBinding> bindings;
};
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -28,18 +28,65 @@
#if ENABLE(WEBGPU)
+#include "Logging.h"
+
namespace WebCore {
-Ref<WebGPUBuffer> WebGPUBuffer::create(Ref<GPUBuffer>&& buffer)
+Ref<WebGPUBuffer> WebGPUBuffer::create(RefPtr<GPUBuffer>&& buffer)
{
return adoptRef(*new WebGPUBuffer(WTFMove(buffer)));
}
-WebGPUBuffer::WebGPUBuffer(Ref<GPUBuffer>&& buffer)
+WebGPUBuffer::WebGPUBuffer(RefPtr<GPUBuffer>&& buffer)
: m_buffer(WTFMove(buffer))
{
}
+void WebGPUBuffer::mapReadAsync(BufferMappingPromise&& promise)
+{
+ rejectOrRegisterPromiseCallback(WTFMove(promise), true);
+}
+
+void WebGPUBuffer::mapWriteAsync(BufferMappingPromise&& promise)
+{
+ rejectOrRegisterPromiseCallback(WTFMove(promise), false);
+}
+
+void WebGPUBuffer::unmap()
+{
+ if (m_buffer)
+ m_buffer->unmap();
+}
+
+void WebGPUBuffer::destroy()
+{
+ if (!m_buffer)
+ LOG(WebGPU, "GPUBuffer::destroy(): Invalid operation!");
+ else {
+ m_buffer->destroy();
+ // FIXME: Ensure that GPUBuffer is kept alive by resource bindings if still being used by GPU.
+ m_buffer = nullptr;
+ }
+}
+
+void WebGPUBuffer::rejectOrRegisterPromiseCallback(BufferMappingPromise&& promise, bool isRead)
+{
+ if (!m_buffer) {
+ LOG(WebGPU, "GPUBuffer::map%sAsync(): Invalid operation!", isRead ? "Read" : "Write");
+ promise.reject();
+ return;
+ }
+
+ m_buffer->registerMappingCallback([promise = WTFMove(promise)] (JSC::ArrayBuffer* arrayBuffer) mutable {
+ if (!arrayBuffer) {
+ promise.reject();
+ return;
+ }
+
+ promise.resolve(arrayBuffer);
+ }, isRead);
+}
+
} // namespace WebCore
#endif // ENABLE(WEBGPU)
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -28,26 +28,37 @@
#if ENABLE(WEBGPU)
#include "GPUBuffer.h"
-
+#include "GPUBufferUsage.h"
+#include "JSDOMPromiseDeferred.h"
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+namespace JSC {
+class ArrayBuffer;
+}
+
namespace WebCore {
+struct GPUBufferDescriptor;
+
class WebGPUBuffer : public RefCounted<WebGPUBuffer> {
public:
- static Ref<WebGPUBuffer> create(Ref<GPUBuffer>&&);
+ static Ref<WebGPUBuffer> create(RefPtr<GPUBuffer>&&);
- const GPUBuffer& buffer() const { return m_buffer.get(); }
+ RefPtr<const GPUBuffer> buffer() const { return m_buffer; }
- JSC::ArrayBuffer* mapping() const { return m_buffer->mapping(); }
- void unmap() { /* FIXME: Unimplemented stub. */ }
- void destroy() { /* FIXME: Unimplemented stub. */ }
+ using BufferMappingPromise = DOMPromiseDeferred<IDLInterface<JSC::ArrayBuffer*>>;
+ void mapReadAsync(BufferMappingPromise&&);
+ void mapWriteAsync(BufferMappingPromise&&);
+ void unmap();
+ void destroy();
private:
- explicit WebGPUBuffer(Ref<GPUBuffer>&&);
+ explicit WebGPUBuffer(RefPtr<GPUBuffer>&&);
- Ref<GPUBuffer> m_buffer;
+ void rejectOrRegisterPromiseCallback(BufferMappingPromise&&, bool);
+
+ RefPtr<GPUBuffer> m_buffer;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl 2019-02-23 23:24:27 UTC (rev 241996)
@@ -28,7 +28,10 @@
EnabledAtRuntime=WebGPU,
ImplementationLacksVTable
] interface WebGPUBuffer {
- readonly attribute ArrayBuffer? mapping;
+ //void setSubData(u32 offset, ArrayBuffer data);
+
+ Promise<ArrayBuffer> mapReadAsync();
+ Promise<ArrayBuffer> mapWriteAsync();
void unmap();
void destroy();
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUCommandBuffer.cpp (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUCommandBuffer.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUCommandBuffer.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -47,7 +47,7 @@
RefPtr<WebGPURenderPassEncoder> WebGPUCommandBuffer::beginRenderPass(WebGPURenderPassDescriptor&& descriptor)
{
- auto gpuDescriptor = descriptor.validateAndConvertToGPUVersion();
+ auto gpuDescriptor = descriptor.asGPURenderPassDescriptor();
if (!gpuDescriptor)
return nullptr;
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -55,7 +55,6 @@
#include "WebGPUShaderModule.h"
#include "WebGPUShaderModuleDescriptor.h"
#include "WebGPUTexture.h"
-#include <wtf/Variant.h>
namespace WebCore {
@@ -73,11 +72,10 @@
UNUSED_PARAM(m_adapter);
}
-RefPtr<WebGPUBuffer> WebGPUDevice::createBuffer(GPUBufferDescriptor&& descriptor) const
+Ref<WebGPUBuffer> WebGPUDevice::createBuffer(GPUBufferDescriptor&& descriptor) const
{
- if (auto buffer = m_device->createBuffer(WTFMove(descriptor)))
- return WebGPUBuffer::create(buffer.releaseNonNull());
- return nullptr;
+ auto buffer = m_device->tryCreateBuffer(WTFMove(descriptor));
+ return WebGPUBuffer::create(WTFMove(buffer));
}
Ref<WebGPUTexture> WebGPUDevice::createTexture(GPUTextureDescriptor&& descriptor) const
@@ -104,44 +102,11 @@
Ref<WebGPUBindGroup> WebGPUDevice::createBindGroup(WebGPUBindGroupDescriptor&& descriptor) const
{
- if (!descriptor.layout || !descriptor.layout->bindGroupLayout()) {
- LOG(WebGPU, "WebGPUDevice::createBindGroup(): Invalid WebGPUBindGroupLayout!");
+ auto gpuDescriptor = descriptor.asGPUBindGroupDescriptor();
+ if (!gpuDescriptor)
return WebGPUBindGroup::create(nullptr);
- }
- if (descriptor.bindings.size() != descriptor.layout->bindGroupLayout()->bindingsMap().size()) {
- LOG(WebGPU, "WebGPUDevice::createBindGroup(): Mismatched number of WebGPUBindGroupLayoutBindings and WebGPUBindGroupBindings!");
- return WebGPUBindGroup::create(nullptr);
- }
-
- auto bindingResourceVisitor = WTF::makeVisitor([] (RefPtr<WebGPUTextureView> view) -> Optional<GPUBindingResource> {
- if (view)
- return static_cast<GPUBindingResource>(view->texture());
- return WTF::nullopt;
- }, [] (const WebGPUBufferBinding& binding) -> Optional<GPUBindingResource> {
- if (binding.buffer)
- return static_cast<GPUBindingResource>(GPUBufferBinding { binding.buffer->buffer(), binding.offset, binding.size });
- return WTF::nullopt;
- });
-
- Vector<GPUBindGroupBinding> bindGroupBindings;
- bindGroupBindings.reserveCapacity(descriptor.bindings.size());
-
- for (const auto& binding : descriptor.bindings) {
- if (!descriptor.layout->bindGroupLayout()->bindingsMap().contains(binding.binding)) {
- LOG(WebGPU, "WebGPUDevice::createBindGroup(): WebGPUBindGroupBinding %lu not found in WebGPUBindGroupLayout!", binding.binding);
- return WebGPUBindGroup::create(nullptr);
- }
-
- auto bindingResource = WTF::visit(bindingResourceVisitor, binding.resource);
- if (bindingResource)
- bindGroupBindings.uncheckedAppend(GPUBindGroupBinding { binding.binding, WTFMove(bindingResource.value()) });
- else {
- LOG(WebGPU, "WebGPUDevice::createBindGroup(): Invalid WebGPUBindingResource for binding %lu in WebGPUBindGroupBindings!", binding.binding);
- return WebGPUBindGroup::create(nullptr);
- }
- }
- auto bindGroup = GPUBindGroup::create(GPUBindGroupDescriptor { descriptor.layout->bindGroupLayout().releaseNonNull(), WTFMove(bindGroupBindings) });
+ auto bindGroup = GPUBindGroup::create(WTFMove(*gpuDescriptor));
return WebGPUBindGroup::create(WTFMove(bindGroup));
}
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -62,7 +62,7 @@
const WebGPUAdapter& adapter() const { return m_adapter.get(); }
const GPUDevice& device() const { return m_device.get(); }
- RefPtr<WebGPUBuffer> createBuffer(GPUBufferDescriptor&&) const;
+ Ref<WebGPUBuffer> createBuffer(GPUBufferDescriptor&&) const;
Ref<WebGPUTexture> createTexture(GPUTextureDescriptor&&) const;
Ref<WebGPUBindGroupLayout> createBindGroupLayout(WebGPUBindGroupLayoutDescriptor&&) const;
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.cpp (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -45,7 +45,7 @@
{
}
-Optional<GPURenderPassDescriptor> WebGPURenderPassDescriptor::validateAndConvertToGPUVersion() const
+Optional<GPURenderPassDescriptor> WebGPURenderPassDescriptor::asGPURenderPassDescriptor() const
{
// FIXME: Improve error checking as WebGPURenderPassDescriptor is added to spec.
if (colorAttachments.isEmpty()) {
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.h (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassDescriptor.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -46,7 +46,7 @@
};
struct WebGPURenderPassDescriptor {
- Optional<GPURenderPassDescriptor> validateAndConvertToGPUVersion() const;
+ Optional<GPURenderPassDescriptor> asGPURenderPassDescriptor() const;
Vector<WebGPURenderPassColorAttachmentDescriptor> colorAttachments;
Optional<WebGPURenderPassDepthStencilAttachmentDescriptor> depthStencilAttachment;
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.cpp (241995 => 241996)
--- trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -49,20 +49,36 @@
void WebGPURenderPassEncoder::setVertexBuffers(unsigned long startSlot, Vector<RefPtr<WebGPUBuffer>>&& buffers, Vector<unsigned long long>&& offsets)
{
+#if !LOG_DISABLED
+ const char* const functionName = "GPURenderPassEncoder::setVertexBuffers()";
+#endif
if (buffers.isEmpty() || buffers.size() != offsets.size()) {
- LOG(WebGPU, "WebGPURenderPassEncoder::setVertexBuffers: Invalid number of buffers or offsets!");
+ LOG(WebGPU, "%s: Invalid number of buffers or offsets!", functionName);
return;
}
if (startSlot + buffers.size() > maxVertexBuffers) {
- LOG(WebGPU, "WebGPURenderPassEncoder::setVertexBuffers: Invalid startSlot %lu for %lu buffers!", startSlot, buffers.size());
+ LOG(WebGPU, "%s: Invalid startSlot %lu for %lu buffers!", functionName, startSlot, buffers.size());
return;
}
- auto gpuBuffers = buffers.map([] (const auto& buffer) -> Ref<const GPUBuffer> {
- return buffer->buffer();
- });
+ Vector<Ref<const GPUBuffer>> gpuBuffers;
+ gpuBuffers.reserveCapacity(buffers.size());
+ for (const auto& buffer : buffers) {
+ if (!buffer || !buffer->buffer()) {
+ LOG(WebGPU, "%s: Invalid or destroyed buffer in list!", functionName);
+ return;
+ }
+
+ if (!buffer->buffer()->isVertex()) {
+ LOG(WebGPU, "%s: Buffer was not created with VERTEX usage!", functionName);
+ return;
+ }
+
+ gpuBuffers.uncheckedAppend(buffer->buffer().releaseNonNull());
+ }
+
m_passEncoder->setVertexBuffers(startSlot, WTFMove(gpuBuffers), WTFMove(offsets));
}
Modified: trunk/Source/WebCore/Sources.txt (241995 => 241996)
--- trunk/Source/WebCore/Sources.txt 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/Sources.txt 2019-02-23 23:24:27 UTC (rev 241996)
@@ -348,6 +348,7 @@
Modules/webgpu/WHLSL/AST/WHLSLUnsignedIntegerLiteral.cpp
Modules/webgpu/WebGPU.cpp
Modules/webgpu/WebGPUBindGroup.cpp
+Modules/webgpu/WebGPUBindGroupDescriptor.cpp
Modules/webgpu/WebGPUAdapter.cpp
Modules/webgpu/WebGPUBindGroupLayout.cpp
Modules/webgpu/WebGPUBuffer.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (241995 => 241996)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-02-23 23:24:27 UTC (rev 241996)
@@ -4255,6 +4255,7 @@
D05CED2A0A40BB2C00C5AF38 /* FormatBlockCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D05CED280A40BB2C00C5AF38 /* FormatBlockCommand.h */; };
D06C0D8F0CFD11460065F43F /* RemoveFormatCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C0D8D0CFD11460065F43F /* RemoveFormatCommand.h */; };
D07DEABA0A36554A00CA30F8 /* InsertListCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */; };
+ D084033C221CBF6900007205 /* GPUBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D084033A221CBF5400007205 /* GPUBuffer.cpp */; };
D0843A4B20FEBE3D00FE860E /* GraphicsContext3DManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D0843A4A20FEBE3D00FE860E /* GraphicsContext3DManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
D086FE9809D53AAB005BC74D /* UnlinkCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = D086FE9609D53AAB005BC74D /* UnlinkCommand.h */; };
D08B00E220A282490004BC0A /* WebGLCompressedTextureASTC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A20D562092A0A600E0C259 /* WebGLCompressedTextureASTC.cpp */; };
@@ -14075,6 +14076,8 @@
D07DEAB80A36554A00CA30F8 /* InsertListCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InsertListCommand.h; sourceTree = "<group>"; };
D083D98421C48050008E8EFF /* GPUBindGroupLayoutDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUBindGroupLayoutDescriptor.h; sourceTree = "<group>"; };
D083D98621C4813E008E8EFF /* WebGPUBindGroupLayoutDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebGPUBindGroupLayoutDescriptor.h; path = Modules/streams/WebGPUBindGroupLayoutDescriptor.h; sourceTree = SOURCE_ROOT; };
+ D084033A221CBF5400007205 /* GPUBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GPUBuffer.cpp; sourceTree = "<group>"; };
+ D084033D221E186400007205 /* WebGPUBindGroupDescriptor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebGPUBindGroupDescriptor.cpp; sourceTree = "<group>"; };
D0843A4A20FEBE3D00FE860E /* GraphicsContext3DManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GraphicsContext3DManager.h; sourceTree = "<group>"; };
D0843A4C20FEC16500FE860E /* GraphicsContext3DManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DManager.cpp; sourceTree = "<group>"; };
D086FE9609D53AAB005BC74D /* UnlinkCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkCommand.h; sourceTree = "<group>"; };
@@ -18481,6 +18484,7 @@
D02454D021C4A41C00B73628 /* GPUBindGroupLayout.h */,
D0B8BB0121C46E78000C7681 /* GPUBindGroupLayoutBinding.h */,
D083D98421C48050008E8EFF /* GPUBindGroupLayoutDescriptor.h */,
+ D084033A221CBF5400007205 /* GPUBuffer.cpp */,
D0D8649221B760F2003C983C /* GPUBuffer.h */,
D0BE104A21E6872F00E42A89 /* GPUBufferBinding.h */,
D0D8648721B64CAA003C983C /* GPUBufferDescriptor.h */,
@@ -26107,6 +26111,7 @@
D0BE106221E6C0EB00E42A89 /* WebGPUBindGroup.idl */,
D0BE104F21E69F8300E42A89 /* WebGPUBindGroupBinding.h */,
D0BE105021E69F8300E42A89 /* WebGPUBindGroupBinding.idl */,
+ D084033D221E186400007205 /* WebGPUBindGroupDescriptor.cpp */,
D0BE105221E6AA0D00E42A89 /* WebGPUBindGroupDescriptor.h */,
D0BE105321E6AA0D00E42A89 /* WebGPUBindGroupDescriptor.idl */,
D003287A21C8645B00622AA6 /* WebGPUBindGroupLayout.cpp */,
@@ -32945,6 +32950,7 @@
51A9D9E9195B931F001B2B5C /* GamepadManager.cpp in Sources */,
515BE1911D54F5FB00DD7C68 /* GamepadProvider.cpp in Sources */,
837964CF1F8DB69D00218EA0 /* GeolocationPositionIOS.mm in Sources */,
+ D084033C221CBF6900007205 /* GPUBuffer.cpp in Sources */,
6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */,
7C3E510B18DF8F3500C112F7 /* HTMLConverter.mm in Sources */,
A8D06B3A0A265DCD005E7203 /* HTMLNames.cpp in Sources */,
Copied: trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.cpp (from rev 241995, trunk/Source/WebCore/Modules/webgpu/WebGPUBindGroupDescriptor.h) (0 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.cpp (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -0,0 +1,40 @@
+/*
+ * 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 "GPUBuffer.h"
+
+#if ENABLE(WEBGPU)
+
+namespace WebCore {
+
+GPUBuffer::PendingMappingCallback::PendingMappingCallback(MappingCallback&& pending)
+ : callback(WTFMove(pending))
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGPU)
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -27,6 +27,9 @@
#if ENABLE(WEBGPU)
+#include "DeferrableTask.h"
+#include "GPUBufferUsage.h"
+#include <wtf/Function.h>
#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
#include <wtf/RetainPtr.h>
@@ -50,17 +53,57 @@
public:
~GPUBuffer();
- static RefPtr<GPUBuffer> create(const GPUDevice&, GPUBufferDescriptor&&);
+ static RefPtr<GPUBuffer> tryCreate(const GPUDevice&, GPUBufferDescriptor&&);
PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); }
+ bool isVertex() const { return m_isVertex; }
+ bool isUniform() const { return m_isUniform; }
+ bool isStorage() const { return m_isStorage; }
+ bool isReadOnly() const { return m_isReadOnly; }
- JSC::ArrayBuffer* mapping() const { return m_mapping.get(); }
+ using MappingCallback = WTF::Function<void(JSC::ArrayBuffer*)>;
+ void registerMappingCallback(MappingCallback&&, bool);
+ void unmap();
+ void destroy();
private:
- explicit GPUBuffer(PlatformBufferSmartPtr&&, RefPtr<JSC::ArrayBuffer>&&);
+ struct PendingMappingCallback : public RefCounted<PendingMappingCallback> {
+ static Ref<PendingMappingCallback> create(MappingCallback&& callback)
+ {
+ return adoptRef(*new PendingMappingCallback(WTFMove(callback)));
+ }
+ MappingCallback callback;
+
+ private:
+ PendingMappingCallback(MappingCallback&&);
+ };
+
+ GPUBuffer(PlatformBufferSmartPtr&&, const GPUBufferDescriptor&);
+
+ static RefPtr<GPUBuffer> tryCreateSharedBuffer(const GPUDevice&, const GPUBufferDescriptor&);
+ JSC::ArrayBuffer* stagingBufferForRead();
+ JSC::ArrayBuffer* stagingBufferForWrite();
+
+ bool isMappable() const { return m_isMapWrite || m_isMapRead; }
+ bool isMapWriteable() const { return m_isMapWrite && !m_pendingCallback; }
+ bool isMapReadable() const { return m_isMapRead && !m_pendingCallback; }
+
PlatformBufferSmartPtr m_platformBuffer;
- RefPtr<JSC::ArrayBuffer> m_mapping;
+
+ RefPtr<JSC::ArrayBuffer> m_stagingBuffer;
+ RefPtr<PendingMappingCallback> m_pendingCallback;
+ DeferrableTask<Timer> m_mappingCallbackTask;
+
+ unsigned long m_byteLength;
+ unsigned m_numScheduledCommandBuffers = 0;
+ bool m_isMapWrite;
+ bool m_isMapRead;
+ bool m_isDestroyed = false;
+ bool m_isVertex;
+ bool m_isUniform;
+ bool m_isStorage;
+ bool m_isReadOnly;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUBufferUsage.h (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUBufferUsage.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUBufferUsage.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -35,7 +35,7 @@
class GPUBufferUsage : public RefCounted<GPUBufferUsage> {
public:
- enum class Flags : GPUBufferUsageFlags {
+ enum Flags : GPUBufferUsageFlags {
None = 0,
MapRead = 1,
MapWrite = 2,
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp 2019-02-23 23:24:27 UTC (rev 241996)
@@ -44,9 +44,9 @@
namespace WebCore {
-RefPtr<GPUBuffer> GPUDevice::createBuffer(GPUBufferDescriptor&& descriptor) const
+RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(GPUBufferDescriptor&& descriptor) const
{
- return GPUBuffer::create(*this, WTFMove(descriptor));
+ return GPUBuffer::tryCreate(*this, WTFMove(descriptor));
}
RefPtr<GPUTexture> GPUDevice::tryCreateTexture(GPUTextureDescriptor&& descriptor) const
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h 2019-02-23 23:24:27 UTC (rev 241996)
@@ -60,7 +60,7 @@
public:
static RefPtr<GPUDevice> create(Optional<GPURequestAdapterOptions>&&);
- RefPtr<GPUBuffer> createBuffer(GPUBufferDescriptor&&) const;
+ RefPtr<GPUBuffer> tryCreateBuffer(GPUBufferDescriptor&&) const;
RefPtr<GPUTexture> tryCreateTexture(GPUTextureDescriptor&&) const;
RefPtr<GPUBindGroupLayout> tryCreateBindGroupLayout(GPUBindGroupLayoutDescriptor&&) const;
Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2019-02-23 23:24:27 UTC (rev 241996)
@@ -31,67 +31,152 @@
#import "GPUBufferDescriptor.h"
#import "GPUDevice.h"
#import "Logging.h"
-
-#import <Foundation/NSRange.h>
#import <_javascript_Core/ArrayBuffer.h>
#import <Metal/Metal.h>
-#import <wtf/Gigacage.h>
-#import <wtf/PageBlock.h>
+#import <wtf/BlockObjCExceptions.h>
namespace WebCore {
-RefPtr<GPUBuffer> GPUBuffer::create(const GPUDevice& device, GPUBufferDescriptor&& descriptor)
+RefPtr<GPUBuffer> GPUBuffer::tryCreateSharedBuffer(const GPUDevice& device, const GPUBufferDescriptor& descriptor)
{
+ ASSERT(device.platformDevice());
+
+ RetainPtr<MTLBuffer> mtlBuffer;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ mtlBuffer = adoptNS([device.platformDevice() newBufferWithLength:descriptor.size options: MTLResourceCPUCacheModeDefaultCache]);
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ if (!mtlBuffer) {
+ LOG(WebGPU, "GPUBuffer::create(): Unable to create MTLBuffer!");
+ return nullptr;
+ }
+
+ return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), descriptor));
+}
+
+static const auto readOnlyMask = GPUBufferUsage::Index | GPUBufferUsage::Vertex | GPUBufferUsage::Uniform | GPUBufferUsage::TransferSrc;
+
+RefPtr<GPUBuffer> GPUBuffer::tryCreate(const GPUDevice& device, GPUBufferDescriptor&& descriptor)
+{
if (!device.platformDevice()) {
LOG(WebGPU, "GPUBuffer::create(): Invalid GPUDevice!");
return nullptr;
}
- size_t pageSize = WTF::pageSize();
- size_t pageAlignedSize = roundUpToMultipleOf(pageSize, descriptor.size);
- void* pageAlignedCopy = Gigacage::tryAlignedMalloc(Gigacage::Primitive, pageSize, pageAlignedSize);
- if (!pageAlignedCopy) {
- LOG(WebGPU, "GPUBuffer::create(): Unable to allocate memory!");
+ if ((descriptor.usage & GPUBufferUsage::MapWrite) && (descriptor.usage & GPUBufferUsage::MapRead)) {
+ LOG(WebGPU, "GPUBuffer::create(): Buffer cannot have both MAP_READ and MAP_WRITE usage!");
return nullptr;
}
- auto arrayBuffer = ArrayBuffer::createFromBytes(pageAlignedCopy, descriptor.size, [] (void* ptr) {
- Gigacage::alignedFree(Gigacage::Primitive, ptr);
- });
- arrayBuffer->ref();
- ArrayBuffer* arrayBufferContents = arrayBuffer.ptr();
- // FIXME: Default this MTLResourceOptions.
- PlatformBufferSmartPtr mtlBuffer = adoptNS([device.platformDevice()
- newBufferWithBytesNoCopy:arrayBuffer->data()
- length:pageAlignedSize
- options:MTLResourceCPUCacheModeDefaultCache
- deallocator:^(void*, NSUInteger) {
- arrayBufferContents->deref();
- }]);
-
- if (!mtlBuffer) {
- LOG(WebGPU, "GPUBuffer::create(): Unable to create MTLBuffer!");
- arrayBuffer->deref();
+ if ((descriptor.usage & readOnlyMask) && (descriptor.usage & GPUBufferUsage::Storage)) {
+ LOG(WebGPU, "GPUBuffer::create(): Buffer cannot have both STORAGE and a read-only usage!");
return nullptr;
}
- return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(arrayBuffer)));
+ // Mappable buffers need (default) shared storage allocation.
+ if (descriptor.usage & (GPUBufferUsage::MapWrite | GPUBufferUsage::MapRead))
+ return tryCreateSharedBuffer(device, descriptor);
+
+ LOG(WebGPU, "GPUBuffer::create(): Support for non-mapped buffers not implemented!");
+ return nullptr;
}
-GPUBuffer::GPUBuffer(PlatformBufferSmartPtr&& platformBuffer, RefPtr<ArrayBuffer>&& arrayBuffer)
- : m_platformBuffer(WTFMove(platformBuffer))
- , m_mapping(WTFMove(arrayBuffer))
+GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, const GPUBufferDescriptor& descriptor)
+ : m_platformBuffer(WTFMove(buffer))
+ , m_byteLength(descriptor.size)
+ , m_isMapWrite(descriptor.usage & GPUBufferUsage::MapWrite)
+ , m_isMapRead(descriptor.usage & GPUBufferUsage::MapRead)
+ , m_isVertex(descriptor.usage & GPUBufferUsage::Vertex)
+ , m_isUniform(descriptor.usage & GPUBufferUsage::Uniform)
+ , m_isStorage(descriptor.usage & GPUBufferUsage::Storage)
+ , m_isReadOnly(descriptor.usage & readOnlyMask)
{
}
GPUBuffer::~GPUBuffer()
{
- if (m_mapping) {
- m_mapping->deref();
- m_mapping = nullptr;
+ unmap();
+}
+
+void GPUBuffer::registerMappingCallback(MappingCallback&& callback, bool isRead)
+{
+ // Reject if request is invalid.
+ if (isRead && !isMapReadable()) {
+ LOG(WebGPU, "GPUBuffer::mapReadAsync(): Invalid operation!");
+ callback(nullptr);
+ return;
}
+ if (!isRead && !isMapWriteable()) {
+ LOG(WebGPU, "GPUBuffer::mapWriteAsync(): Invalid operation!");
+ callback(nullptr);
+ return;
+ }
+
+ ASSERT(!m_pendingCallback && !m_mappingCallbackTask.hasPendingTask());
+
+ // An existing callback means this buffer is in the mapped state.
+ m_pendingCallback = PendingMappingCallback::create(WTFMove(callback));
+
+ // If GPU is not using this buffer, run the callback ASAP.
+ if (!m_numScheduledCommandBuffers) {
+ m_mappingCallbackTask.scheduleTask([this, protectedThis = makeRef(*this)] () mutable {
+ ASSERT(m_pendingCallback);
+
+ m_pendingCallback->callback(m_isMapRead ? stagingBufferForRead() : stagingBufferForWrite());
+ });
+ }
}
+JSC::ArrayBuffer* GPUBuffer::stagingBufferForRead()
+{
+ if (!m_stagingBuffer)
+ m_stagingBuffer = ArrayBuffer::create(m_platformBuffer.get().contents, m_byteLength);
+ else
+ memcpy(m_stagingBuffer->data(), m_platformBuffer.get().contents, m_byteLength);
+
+ return m_stagingBuffer.get();
+}
+
+JSC::ArrayBuffer* GPUBuffer::stagingBufferForWrite()
+{
+ m_stagingBuffer = ArrayBuffer::create(1, m_byteLength);
+ return m_stagingBuffer.get();
+}
+
+void GPUBuffer::unmap()
+{
+ if (!isMappable()) {
+ LOG(WebGPU, "GPUBuffer::unmap(): Buffer is not mappable!");
+ return;
+ }
+
+ if (m_stagingBuffer && m_isMapWrite) {
+ memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength);
+ m_stagingBuffer = nullptr;
+ }
+
+ if (m_pendingCallback) {
+ m_mappingCallbackTask.cancelTask();
+ m_pendingCallback->callback(nullptr);
+ m_pendingCallback = nullptr;
+ }
+}
+
+void GPUBuffer::destroy()
+{
+ if (isMappable())
+ unmap();
+
+ m_isDestroyed = true;
+
+ // FIXME: If GPU is still using the MTLBuffer, it will be released after all relevant commands have executed.
+ if (!m_numScheduledCommandBuffers)
+ m_platformBuffer = nullptr;
+}
+
} // namespace WebCore
#endif // ENABLE(WEBGPU)
Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm (241995 => 241996)
--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm 2019-02-23 20:49:39 UTC (rev 241995)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm 2019-02-23 23:24:27 UTC (rev 241996)
@@ -61,9 +61,9 @@
}
auto& bufferBinding = WTF::get<GPUBufferBinding>(resource);
- auto buffer = bufferBinding.buffer->platformBuffer();
+ auto mtlBuffer = bufferBinding.buffer->platformBuffer();
- if (!buffer) {
+ if (!mtlBuffer) {
LOG(WebGPU, "%s: Invalid MTLBuffer in GPUBufferBinding!", functionName);
return;
}
@@ -70,8 +70,8 @@
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- [argumentEncoder setBuffer:buffer offset:bufferBinding.offset atIndex:index];
- useResource(buffer, MTLResourceUsageRead);
+ [argumentEncoder setBuffer:mtlBuffer offset:bufferBinding.offset atIndex:index];
+ useResource(mtlBuffer, bufferBinding.buffer->isReadOnly() ? MTLResourceUsageRead : MTLResourceUsageRead | MTLResourceUsageWrite);
END_BLOCK_OBJC_EXCEPTIONS;
}