Diff
Modified: trunk/LayoutTests/ChangeLog (246216 => 246217)
--- trunk/LayoutTests/ChangeLog 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/ChangeLog 2019-06-07 22:24:55 UTC (rev 246217)
@@ -1,3 +1,29 @@
+2019-06-07 Justin Fan <justin_...@apple.com>
+
+ [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped
+ https://bugs.webkit.org/show_bug.cgi?id=198591
+
+ Reviewed by Myles C. Maxfield.
+
+ GPUBuffer.setSubData has been removed from the WebGPU implementation.
+ GPUDevice.createBufferMapped has been added to the WebGPU implementation.
+ Replace all setSubData calls with appropriate replacements.
+
+ * webgpu/blend-triangle-strip.html:
+ * webgpu/blit-commands.html:
+ * webgpu/buffer-command-buffer-races.html:
+ * webgpu/buffer-resource-triangles.html:
+ * webgpu/compute-squares.html:
+ * webgpu/depth-enabled-triangle-strip.html:
+ * webgpu/draw-indexed-triangles.html:
+ * webgpu/js/webgpu-functions.js:
+ (createBufferWithData):
+ (async.mapWriteDataToBuffer):
+ * webgpu/map-read-buffers-expected.txt:
+ * webgpu/map-read-buffers.html:
+ * webgpu/texture-triangle-strip.html:
+ * webgpu/vertex-buffer-triangle-strip.html:
+
2019-06-07 Per Arne Vollan <pvol...@apple.com>
Layout Test fast/events/fire-mousedown-while-pressing-mouse-button.html is failing
Modified: trunk/LayoutTests/webgpu/blend-triangle-strip.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/blend-triangle-strip.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/blend-triangle-strip.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -75,8 +75,7 @@
1, 1, 0, 1,
1, -1, 0, 1
]);
- const vertexBuffer = device.createBuffer({ size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- vertexBuffer.setSubData(0, vertexData.buffer);
+ const vertexBuffer = createBufferWithData(device, { size: vertexData.byteLength, usage: GPUBufferUsage.VERTEX }, vertexData.buffer);
const context = canvas.getContext("gpu");
const swapChain = context.configureSwapChain({ device: device, format: "bgra8unorm" });
Modified: trunk/LayoutTests/webgpu/blit-commands.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/blit-commands.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/blit-commands.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -30,11 +30,11 @@
const bufferDescriptor = {
size: imageData.data.byteLength,
- usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST
+ usage: GPUBufferUsage.TRANSFER_SRC
};
- const bufferA = device.createBuffer(bufferDescriptor);
- bufferA.setSubData(0, imageData.data.buffer);
+ bufferA = createBufferWithData(device, bufferDescriptor, imageData.data.buffer);
+ bufferDescriptor.usage |= GPUBufferUsage.TRANSFER_DST;
const bufferB = device.createBuffer(bufferDescriptor);
const bufferViewB = {
buffer: bufferB,
Modified: trunk/LayoutTests/webgpu/buffer-command-buffer-races.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/buffer-command-buffer-races.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/buffer-command-buffer-races.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -63,10 +63,8 @@
}
function createAndSetVertexBuffer(device, vertices) {
- const floatArray = new Float32Array(vertices);
- const buffer = device.createBuffer({ size: floatArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- buffer.setSubData(0, floatArray.buffer);
- return buffer;
+ const vertexArray = new Float32Array(vertices)
+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}
function drawAndSubmitCommands(device, pipeline, attachment, vertexBuffer, colorBuffer) {
@@ -97,8 +95,7 @@
const greenArray = new Float32Array(green);
const blueArray = new Float32Array(blue);
- const colorBuffer = device.createBuffer({ size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_WRITE });
- colorBuffer.setSubData(0, greenArray.buffer);
+ const colorBuffer = createBufferWithData(device, { size: greenArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE }, greenArray.buffer);
const attachment = {
attachment: swapChain.getCurrentTexture().createDefaultView(),
@@ -126,12 +123,12 @@
/* colorBuffer does not actually contain "green" again until this call. */
colorBuffer.unmap();
- /* setSubData immediately after a submit should not affect the preceding draw call. */
+ /* Writing data immediately after a submit should not affect the preceding draw call. */
drawAndSubmitCommands(device, pipeline, attachment, middleBuffer, colorBuffer);
- colorBuffer.setSubData(0, blueArray.buffer);
+ await mapWriteDataToBuffer(colorBuffer, blueArray.buffer);
/* destroy right after a submit should not affect the draw call. */
- colorBuffer.setSubData(0, greenArray.buffer);
+ await mapWriteDataToBuffer(colorBuffer, greenArray.buffer);
drawAndSubmitCommands(device, pipeline, attachment, upperRightBuffer, colorBuffer);
upperRightBuffer.destroy();
Modified: trunk/LayoutTests/webgpu/buffer-resource-triangles.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/buffer-resource-triangles.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/buffer-resource-triangles.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -81,17 +81,13 @@
}
const vertexSize = 4 * 4;
-const verticesBufferSize = vertexSize * 3;
function createAndUploadVerticesBuffer(device) {
- const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- const arrayBuffer = new Float32Array([
+ const vertexArray = new Float32Array([
0, 1, 0, 1,
-1, -1, 0, 1,
1, -1, 0, 1
- ]).buffer;
-
- buffer.setSubData(0, arrayBuffer);
- return buffer;
+ ]);
+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}
function createFloat4Buffer(device, a, b, promises) {
Modified: trunk/LayoutTests/webgpu/compute-squares.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/compute-squares.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/compute-squares.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -39,8 +39,7 @@
const computeStageDescriptor = { module: shaderModule, entryPoint: "compute" };
const pipeline = device.createComputePipeline({ computeStage: computeStageDescriptor });
- const dataBuffer = device.createBuffer({ size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ });
- dataBuffer.setSubData(0, data.buffer);
+ const dataBuffer = createBufferWithData(device, { size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ }, data.buffer);
const bgLayoutBinding = { binding: dataBinding, visibility: GPUShaderStageBit.COMPUTE, type: "storage-buffer" };
const bgLayout = device.createBindGroupLayout({ bindings: [bgLayoutBinding] });
Modified: trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/depth-enabled-triangle-strip.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -48,18 +48,14 @@
`
function createVertexBuffer(device) {
- const bufferSize = 4 * 4 * 4;
- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- const arrayBuffer = new Float32Array([
+ const vertexArray = new Float32Array([
// float4 xyzw
-1, 1, 0, 1,
-1, -1, 0, 1,
1, 1, 0, 1,
1, -1, 0, 1
- ]).buffer;
-
- buffer.setSubData(0, arrayBuffer);
- return buffer;
+ ]);
+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}
function createVertexInputDescriptor() {
Modified: trunk/LayoutTests/webgpu/draw-indexed-triangles.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/draw-indexed-triangles.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/draw-indexed-triangles.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -53,10 +53,7 @@
1, -1, 0, 1, 0,
1, -1, 0, 1, 1
]);
- const buffer = device.createBuffer({ size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- buffer.setSubData(0, vertexArray.buffer);
-
- return buffer;
+ return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}
const indexBufferOffset = 2048; // Test a buffer offset for index array.
@@ -65,8 +62,15 @@
function createIndexBuffer(device) {
const offsetArray = [1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; });
const indexArray = new Uint32Array([1, 3, 5, 3, 5, 7].map(v => { return v - indexOffset; }));
- const buffer = device.createBuffer({ size: indexArray.byteLength + indexBufferOffset, usage: GPUBufferUsage.INDEX | GPUBufferUsage.TRANSFER_DST });
- buffer.setSubData(indexBufferOffset, indexArray.buffer);
+ const buffer = createBufferWithData(
+ device,
+ {
+ size: indexArray.byteLength + indexBufferOffset,
+ usage: GPUBufferUsage.INDEX
+ },
+ indexArray.buffer,
+ indexBufferOffset
+ );
return buffer;
}
Modified: trunk/LayoutTests/webgpu/js/webgpu-functions.js (246216 => 246217)
--- trunk/LayoutTests/webgpu/js/webgpu-functions.js 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/js/webgpu-functions.js 2019-06-07 22:24:55 UTC (rev 246217)
@@ -87,4 +87,19 @@
renderPassEncoder.setPipeline(renderPipeline);
renderPassEncoder.draw(4, 1, 0, 0);
renderPassEncoder.endPass();
+}
+
+function createBufferWithData(device, descriptor, data, offset = 0) {
+ const mappedBuffer = device.createBufferMapped(descriptor);
+ const dataArray = new Uint8Array(mappedBuffer[1]);
+ dataArray.set(new Uint8Array(data), offset);
+ mappedBuffer[0].unmap();
+ return mappedBuffer[0];
+}
+
+async function mapWriteDataToBuffer(buffer, data, offset = 0) {
+ const arrayBuffer = await buffer.mapWriteAsync();
+ const writeArray = new Uint8Array(arrayBuffer);
+ writeArray.set(new Uint8Array(data), offset);
+ buffer.unmap();
}
\ No newline at end of file
Modified: trunk/LayoutTests/webgpu/map-read-buffers-expected.txt (246216 => 246217)
--- trunk/LayoutTests/webgpu/map-read-buffers-expected.txt 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/map-read-buffers-expected.txt 2019-06-07 22:24:55 UTC (rev 246217)
@@ -1,5 +1,6 @@
-PASS setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer.
+PASS mapReadAsync, unmap, and destroy on a GPUBuffer.
+PASS GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped.
PASS Reject a map read on a buffer not created with MAP_READ usage.
PASS Reject a map read on a mapped GPUBuffer.
PASS Reject a pending map read if GPUBuffer is unmapped.
Modified: trunk/LayoutTests/webgpu/map-read-buffers.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/map-read-buffers.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/map-read-buffers.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -1,6 +1,6 @@
<!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] -->
<meta charset=utf-8>
-<title>Tests for setSubData and mapReadAsync on a GPUBuffer.</title>
+<title>Tests for createBufferMapped and mapReadAsync on a GPUBuffer.</title>
<body>
<script src=""
<script src=""
@@ -11,27 +11,17 @@
// Basic mapReadAsync functionality
promise_test(async () => {
- const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ });
+ const buffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.MAP_READ });
assert_true(buffer instanceof GPUBuffer, "createBuffer returned a GPUBuffer");
- let array = new Float32Array([1, 2, 3, 4]);
- buffer.setSubData(0, array.buffer);
-
let arrayBuffer = await buffer.mapReadAsync();
assert_true(arrayBuffer instanceof ArrayBuffer, "first mapReadAsync resolved successfully");
const readArray = new Float32Array(arrayBuffer);
- assert_equals(readArray[3], 4, "successfully map-read value set by setSubData");
+ assert_equals(readArray[0], 0, "successfully access a value from a map read");
buffer.unmap();
- buffer.setSubData(4 * 3, array.slice(0, 1).buffer);
- let arrayBuffer1 = await buffer.mapReadAsync();
- const readArray1 = new Float32Array(arrayBuffer1);
- assert_equals(readArray[3], 1, "successfully setSubData with an offset");
-
- buffer.unmap();
-
const promise = buffer.mapReadAsync(); // This will eventually reject due to buffer.destroy()
buffer.destroy();
@@ -40,8 +30,42 @@
assert_unreached("Buffer was destroyed!");
}, () => {});
- }, "setSubData, mapReadAsync, unmap, and destroy on a GPUBuffer.");
+ }, "mapReadAsync, unmap, and destroy on a GPUBuffer.");
+ // GPUDevice.createBufferMapped
+ promise_test(async () => {
+ const bufferResult = device.createBufferMapped({ size: 16, usage: GPUBufferUsage.MAP_READ });
+ const buffer = bufferResult[0];
+ const arrayBuffer = bufferResult[1];
+
+ assert_true(buffer instanceof GPUBuffer, "createBufferMapped returned a GPUBuffer");
+ assert_true(arrayBuffer instanceof ArrayBuffer, "createBufferMapped returned an ArrayBuffer");
+
+ let array = new Float32Array(arrayBuffer);
+ array.set([1, 2, 3, 4]);
+
+ // Buffer should already be "mapped".
+ await buffer.mapReadAsync().then(() => {
+ assert_unreached("GPUBuffer created via GPUBufferMapped cannot be mapped until after first unmap!");
+ }, () => {});
+
+ buffer.unmap();
+
+ // Buffer should not be re-mappable for writes.
+ await buffer.mapWriteAsync().then(() => {
+ assert_unreached("Buffer was not created with MAP_WRITE!");
+ }, () => {});
+
+ // Read results of original writes.
+ let resultArrayBuffer = await buffer.mapReadAsync();
+ const resultArray = new Float32Array(resultArrayBuffer);
+ resultArray.forEach((v, i) => {
+ assert_equals(v, array[i], "Successfully map-read value written to GPUBuffer mapped on creation");
+ })
+
+ buffer.destroy();
+ }, "GPUBuffer.mapReadAsync on a buffer created via GPUDevice.createBufferMapped.");
+
/* Basic validation */
// FIXME: Test invalid combinations of GPUBufferUsage after implementing error handling.
Modified: trunk/LayoutTests/webgpu/texture-triangle-strip.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/texture-triangle-strip.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/texture-triangle-strip.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -89,8 +89,7 @@
1, 1, 0, 1,
1, -1, 0, 1
]);
- const positionBuffer = device.createBuffer({ size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- positionBuffer.setSubData(0, positionArray.buffer);
+ const positionBuffer = createBufferWithData(device, { size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX }, positionArray.buffer);
const texCoordsArray = new Float32Array([
// float2 texCoords
@@ -99,8 +98,7 @@
1, 0,
1, 1
]);
- const textureCoordBuffer = device.createBuffer({ size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- textureCoordBuffer.setSubData(0, texCoordsArray.buffer);
+ const textureCoordBuffer = createBufferWithData(device, { size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX }, texCoordsArray.buffer);
const vertexInputDescriptor = createVertexInputDescriptor();
@@ -122,10 +120,9 @@
const textureBufferDescriptor = {
size: imageData.data.length,
- usage: GPUBufferUsage.TRANSFER_SRC | GPUBufferUsage.TRANSFER_DST
+ usage: GPUBufferUsage.TRANSFER_SRC
};
- const textureBuffer = device.createBuffer(textureBufferDescriptor);
- textureBuffer.setSubData(0, imageData.data.buffer);
+ const textureBuffer = createBufferWithData(device, textureBufferDescriptor, imageData.data.buffer);
// Create GPUTexture
const textureSize = {
Modified: trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html (246216 => 246217)
--- trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/LayoutTests/webgpu/vertex-buffer-triangle-strip.html 2019-06-07 22:24:55 UTC (rev 246217)
@@ -42,22 +42,22 @@
`
function createVertexBuffer(device) {
- const bufferSize = 4 * 5 * 4;
- const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
- const vertexArrayBuffer0 = new Float32Array([
+ const vertexArray = new Float32Array([
// float4 xyzw, float g
-1, 1, 0, 1, 1,
- -1, -1, 0, 1, 1
- ]).buffer;
- const vertexArrayBuffer1 = new Float32Array([
+ -1, -1, 0, 1, 1,
1, 1, 0, 1, 1,
1, -1, 0, 1, 1
- ]).buffer;
+ ]);
- buffer.setSubData(0, vertexArrayBuffer0);
- buffer.setSubData(4 * 5 * 2, vertexArrayBuffer1);
-
- return buffer;
+ return createBufferWithData(
+ device,
+ {
+ size: vertexArray.byteLength,
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE
+ },
+ vertexArray.buffer
+ );
}
function createVertexInputDescriptor() {
Modified: trunk/Source/WebCore/ChangeLog (246216 => 246217)
--- trunk/Source/WebCore/ChangeLog 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/ChangeLog 2019-06-07 22:24:55 UTC (rev 246217)
@@ -1,3 +1,40 @@
+2019-06-07 Justin Fan <justin_...@apple.com>
+
+ [WebGPU] Remove GPUBuffer.setSubData and implement GPUDevice.createBufferMapped
+ https://bugs.webkit.org/show_bug.cgi?id=198591
+
+ Reviewed by Myles C. Maxfield.
+
+ Remove GPUBuffer.setSubData from the WebGPU API.
+ Add GPUDevice.createBufferMapped to the WebGPU API.
+
+ Existing tests have been updated.
+
+ * Modules/webgpu/WebGPUBuffer.cpp:
+ (WebCore::WebGPUBuffer::setSubData): Deleted.
+ * Modules/webgpu/WebGPUBuffer.h:
+ * Modules/webgpu/WebGPUBuffer.idl:
+ * Modules/webgpu/WebGPUDevice.cpp:
+ (WebCore::WebGPUDevice::createBufferMapped const):
+ * Modules/webgpu/WebGPUDevice.h:
+ * Modules/webgpu/WebGPUDevice.idl:
+ * platform/graphics/gpu/GPUBuffer.h:
+ * platform/graphics/gpu/GPUCommandBuffer.h:
+ * platform/graphics/gpu/GPUDevice.cpp:
+ (WebCore::GPUDevice::tryCreateBuffer):
+ * platform/graphics/gpu/GPUDevice.h:
+ * platform/graphics/gpu/cocoa/GPUBufferMetal.mm:
+ (WebCore::GPUBuffer::tryCreate):
+ (WebCore::GPUBuffer::GPUBuffer):
+ (WebCore::GPUBuffer::state const):
+ (WebCore::GPUBuffer::mapOnCreation):
+ (WebCore::GPUBuffer::commandBufferCompleted):
+ (WebCore::GPUBuffer::copyStagingBufferToGPU):
+ Required to unmap GPUBuffers created with GPU-private storage.
+ (WebCore::GPUBuffer::unmap):
+ (WebCore::GPUBuffer::setSubData): Deleted.
+ (WebCore::GPUBuffer::reuseSubDataBuffer): Deleted.
+
2019-06-07 Michael Catanzaro <mcatanz...@igalia.com>
Fix non-iOS build after r246205
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.cpp 2019-06-07 22:24:55 UTC (rev 246217)
@@ -42,14 +42,6 @@
{
}
-void WebGPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data)
-{
- if (!m_buffer)
- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!");
- else
- m_buffer->setSubData(offset, data);
-}
-
void WebGPUBuffer::mapReadAsync(BufferMappingPromise&& promise)
{
rejectOrRegisterPromiseCallback(WTFMove(promise), true);
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.h 2019-06-07 22:24:55 UTC (rev 246217)
@@ -48,7 +48,6 @@
GPUBuffer* buffer() { return m_buffer.get(); }
const GPUBuffer* buffer() const { return m_buffer.get(); }
- void setSubData(uint64_t, const JSC::ArrayBuffer&);
using BufferMappingPromise = DOMPromiseDeferred<IDLInterface<JSC::ArrayBuffer>>;
void mapReadAsync(BufferMappingPromise&&);
void mapWriteAsync(BufferMappingPromise&&);
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUBuffer.idl 2019-06-07 22:24:55 UTC (rev 246217)
@@ -32,8 +32,6 @@
ImplementationLacksVTable,
InterfaceName=GPUBuffer
] interface WebGPUBuffer {
- void setSubData(u64 offset, ArrayBuffer data);
-
Promise<ArrayBuffer> mapReadAsync();
Promise<ArrayBuffer> mapWriteAsync();
void unmap();
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.cpp 2019-06-07 22:24:55 UTC (rev 246217)
@@ -41,12 +41,13 @@
#include "GPUSamplerDescriptor.h"
#include "GPUShaderModuleDescriptor.h"
#include "GPUTextureDescriptor.h"
+#include "JSDOMConvertBufferSource.h"
+#include "JSWebGPUBuffer.h"
#include "Logging.h"
#include "WebGPUBindGroup.h"
#include "WebGPUBindGroupBinding.h"
#include "WebGPUBindGroupDescriptor.h"
#include "WebGPUBindGroupLayout.h"
-#include "WebGPUBuffer.h"
#include "WebGPUBufferBinding.h"
#include "WebGPUCommandEncoder.h"
#include "WebGPUComputePipeline.h"
@@ -84,6 +85,22 @@
return WebGPUBuffer::create(WTFMove(buffer));
}
+Vector<JSC::JSValue> WebGPUDevice::createBufferMapped(JSC::ExecState& state, const GPUBufferDescriptor& descriptor) const
+{
+ JSC::JSValue wrappedArrayBuffer = JSC::jsNull();
+
+ auto buffer = m_device->tryCreateBuffer(descriptor, true);
+ if (buffer) {
+ auto arrayBuffer = buffer->mapOnCreation();
+ wrappedArrayBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), arrayBuffer);
+ }
+
+ auto webBuffer = WebGPUBuffer::create(WTFMove(buffer));
+ auto wrappedWebBuffer = toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), webBuffer);
+
+ return { wrappedWebBuffer, wrappedArrayBuffer };
+}
+
Ref<WebGPUTexture> WebGPUDevice::createTexture(const GPUTextureDescriptor& descriptor) const
{
auto texture = m_device->tryCreateTexture(descriptor);
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.h 2019-06-07 22:24:55 UTC (rev 246217)
@@ -34,7 +34,13 @@
#include <wtf/Ref.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+namespace JSC {
+class ArrayBuffer;
+class JSValue;
+}
+
namespace WebCore {
class ScriptExecutionContext;
@@ -69,6 +75,7 @@
const GPUDevice& device() const { return m_device.get(); }
Ref<WebGPUBuffer> createBuffer(const GPUBufferDescriptor&) const;
+ Vector<JSC::JSValue> createBufferMapped(JSC::ExecState&, const GPUBufferDescriptor&) const;
Ref<WebGPUTexture> createTexture(const GPUTextureDescriptor&) const;
Ref<WebGPUSampler> createSampler(const GPUSamplerDescriptor&) const;
Modified: trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.idl (246216 => 246217)
--- trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.idl 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/Modules/webgpu/WebGPUDevice.idl 2019-06-07 22:24:55 UTC (rev 246217)
@@ -24,6 +24,8 @@
*/
// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl
+typedef sequence<any> GPUMappedBuffer; // [GPUBuffer, ArrayBuffer]
+
[
Conditional=WEBGPU,
EnabledAtRuntime=WebGPU,
@@ -33,6 +35,7 @@
readonly attribute WebGPUAdapter adapter;
WebGPUBuffer createBuffer(GPUBufferDescriptor descriptor);
+ [CallWith=ExecState] GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
WebGPUTexture createTexture(GPUTextureDescriptor descriptor);
WebGPUSampler createSampler(GPUSamplerDescriptor descriptor);
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h (246216 => 246217)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUBuffer.h 2019-06-07 22:24:55 UTC (rev 246217)
@@ -68,7 +68,7 @@
~GPUBuffer();
- static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&);
+ static RefPtr<GPUBuffer> tryCreate(Ref<GPUDevice>&&, const GPUBufferDescriptor&, bool isMappedOnCreation);
PlatformBuffer *platformBuffer() const { return m_platformBuffer.get(); }
size_t byteLength() const { return m_byteLength; }
@@ -82,14 +82,13 @@
bool isMappable() const { return m_usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead }); }
State state() const;
+ JSC::ArrayBuffer* mapOnCreation();
+
#if USE(METAL)
void commandBufferCommitted(MTLCommandBuffer *);
void commandBufferCompleted();
-
- void reuseSubDataBuffer(RetainPtr<MTLBuffer>&&);
#endif
- void setSubData(uint64_t, const JSC::ArrayBuffer&);
using MappingCallback = WTF::Function<void(JSC::ArrayBuffer*)>;
void registerMappingCallback(MappingCallback&&, bool);
void unmap();
@@ -108,13 +107,13 @@
PendingMappingCallback(MappingCallback&&);
};
+ GPUBuffer(PlatformBufferSmartPtr&&, Ref<GPUDevice>&&, size_t, OptionSet<GPUBufferUsage::Flags>, bool);
static bool validateBufferUsage(const GPUDevice&, OptionSet<GPUBufferUsage::Flags>);
- GPUBuffer(PlatformBufferSmartPtr&&, size_t, OptionSet<GPUBufferUsage::Flags>, Ref<GPUDevice>&&);
-
JSC::ArrayBuffer* stagingBufferForRead();
JSC::ArrayBuffer* stagingBufferForWrite();
void runMappingCallback();
+ void copyStagingBufferToGPU();
bool isMapWrite() const { return m_usage.contains(GPUBufferUsage::Flags::MapWrite); }
bool isMapRead() const { return m_usage.contains(GPUBufferUsage::Flags::MapRead); }
@@ -124,10 +123,6 @@
PlatformBufferSmartPtr m_platformBuffer;
Ref<GPUDevice> m_device;
-#if USE(METAL)
- Vector<RetainPtr<MTLBuffer>> m_subDataBuffers;
-#endif
-
RefPtr<JSC::ArrayBuffer> m_stagingBuffer;
RefPtr<PendingMappingCallback> m_mappingCallback;
DeferrableTask<Timer> m_mappingCallbackTask;
@@ -135,6 +130,7 @@
size_t m_byteLength;
OptionSet<GPUBufferUsage::Flags> m_usage;
unsigned m_numScheduledCommandBuffers { 0 };
+ bool m_isMappedFromCreation { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h (246216 => 246217)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUCommandBuffer.h 2019-06-07 22:24:55 UTC (rev 246217)
@@ -108,7 +108,7 @@
PlatformCommandBufferSmartPtr m_platformCommandBuffer;
Vector<Ref<GPUBuffer>> m_usedBuffers;
Vector<Ref<GPUTexture>> m_usedTextures;
- bool m_isEncodingPass = false;
+ bool m_isEncodingPass { false };
#if USE(METAL)
MTLBlitCommandEncoder *blitEncoder() const;
mutable RetainPtr<MTLBlitCommandEncoder> m_blitEncoder;
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp (246216 => 246217)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.cpp 2019-06-07 22:24:55 UTC (rev 246217)
@@ -50,9 +50,9 @@
namespace WebCore {
-RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor)
+RefPtr<GPUBuffer> GPUDevice::tryCreateBuffer(const GPUBufferDescriptor& descriptor, bool isMappedOnCreation)
{
- return GPUBuffer::tryCreate(makeRef(*this), descriptor);
+ return GPUBuffer::tryCreate(makeRef(*this), descriptor, isMappedOnCreation);
}
RefPtr<GPUTexture> GPUDevice::tryCreateTexture(const GPUTextureDescriptor& descriptor) const
Modified: trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h (246216 => 246217)
--- trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/platform/graphics/gpu/GPUDevice.h 2019-06-07 22:24:55 UTC (rev 246217)
@@ -65,7 +65,7 @@
public:
static RefPtr<GPUDevice> tryCreate(const Optional<GPURequestAdapterOptions>&);
- RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&);
+ RefPtr<GPUBuffer> tryCreateBuffer(const GPUBufferDescriptor&, bool isMappedOnCreation = false);
RefPtr<GPUTexture> tryCreateTexture(const GPUTextureDescriptor&) const;
RefPtr<GPUSampler> tryCreateSampler(const GPUSamplerDescriptor&) const;
Modified: trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm (246216 => 246217)
--- trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2019-06-07 22:18:40 UTC (rev 246216)
+++ trunk/Source/WebCore/platform/graphics/gpu/cocoa/GPUBufferMetal.mm 2019-06-07 22:24:55 UTC (rev 246217)
@@ -62,7 +62,7 @@
return true;
}
-RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor)
+RefPtr<GPUBuffer> GPUBuffer::tryCreate(Ref<GPUDevice>&& device, const GPUBufferDescriptor& descriptor, bool isMappedOnCreation)
{
// MTLBuffer size (NSUInteger) is 32 bits on some platforms.
NSUInteger size = 0;
@@ -75,6 +75,17 @@
if (!validateBufferUsage(device.get(), usage))
return nullptr;
+#if PLATFORM(MAC)
+ // copyBufferToBuffer calls require 4-byte alignment. "Unmapping" a mapped-on-creation GPUBuffer
+ // that is otherwise unmappable requires such a copy to upload data.
+ if (isMappedOnCreation
+ && !usage.containsAny({ GPUBufferUsage::Flags::MapWrite, GPUBufferUsage::Flags::MapRead })
+ && descriptor.size % 4) {
+ LOG(WebGPU, "GPUBuffer::tryCreate(): Data must be aligned to a multiple of 4 bytes!");
+ return nullptr;
+ }
+#endif
+
// FIXME: Metal best practices: Read-only one-time-use data less than 4 KB should not allocate a MTLBuffer and be used in [MTLCommandEncoder set*Bytes] calls instead.
MTLResourceOptions resourceOptions = MTLResourceCPUCacheModeDefaultCache;
@@ -95,14 +106,15 @@
return nullptr;
}
- return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), size, usage, WTFMove(device)));
+ return adoptRef(*new GPUBuffer(WTFMove(mtlBuffer), WTFMove(device), size, usage, isMappedOnCreation));
}
-GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, size_t size, OptionSet<GPUBufferUsage::Flags> usage, Ref<GPUDevice>&& device)
+GPUBuffer::GPUBuffer(RetainPtr<MTLBuffer>&& buffer, Ref<GPUDevice>&& device, size_t size, OptionSet<GPUBufferUsage::Flags> usage, bool isMapped)
: m_platformBuffer(WTFMove(buffer))
, m_device(WTFMove(device))
, m_byteLength(size)
, m_usage(usage)
+ , m_isMappedFromCreation(isMapped)
{
}
@@ -120,69 +132,16 @@
{
if (!m_platformBuffer)
return State::Destroyed;
- if (m_mappingCallback)
+ if (m_isMappedFromCreation || m_mappingCallback)
return State::Mapped;
return State::Unmapped;
}
-void GPUBuffer::setSubData(uint64_t offset, const JSC::ArrayBuffer& data)
+JSC::ArrayBuffer* GPUBuffer::mapOnCreation()
{
- MTLCommandQueue *queue;
- if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue()))
- return;
-
- if (!isTransferDestination() || state() != State::Unmapped) {
- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid operation!");
- return;
- }
-
-#if PLATFORM(MAC)
- if (offset % 4 || data.byteLength() % 4) {
- LOG(WebGPU, "GPUBuffer::setSubData(): Data must be aligned to a multiple of 4 bytes!");
- return;
- }
-#endif
- // MTLBuffer size (NSUInteger) is 32 bits on some platforms.
- auto subDataLength = checkedSum<NSUInteger>(data.byteLength(), offset);
- if (subDataLength.hasOverflowed() || subDataLength.unsafeGet() > m_byteLength) {
- LOG(WebGPU, "GPUBuffer::setSubData(): Invalid offset or data size!");
- return;
- }
-
- if (m_subDataBuffers.isEmpty()) {
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
- m_subDataBuffers.append(adoptNS([m_platformBuffer.get().device newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache]));
- END_BLOCK_OBJC_EXCEPTIONS;
- }
-
- __block auto stagingMtlBuffer = m_subDataBuffers.takeLast();
-
- if (!stagingMtlBuffer || stagingMtlBuffer.get().length < data.byteLength()) {
- LOG(WebGPU, "GPUBuffer::setSubData(): Unable to get staging buffer for provided data!");
- return;
- }
-
- memcpy(stagingMtlBuffer.get().contents, data.data(), data.byteLength());
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
-
- auto commandBuffer = retainPtr([queue commandBuffer]);
- auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]);
-
- [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:static_cast<NSUInteger>(offset) size:stagingMtlBuffer.get().length];
- [blitEncoder endEncoding];
-
- if (isMappable())
- commandBufferCommitted(commandBuffer.get());
-
- auto protectedThis = makeRefPtr(this);
- [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>) {
- protectedThis->reuseSubDataBuffer(WTFMove(stagingMtlBuffer));
- }];
- [commandBuffer commit];
-
- END_BLOCK_OBJC_EXCEPTIONS;
+ ASSERT(m_isMappedFromCreation);
+ return stagingBufferForWrite();
}
#if USE(METAL)
@@ -210,11 +169,6 @@
--m_numScheduledCommandBuffers;
}
-
-void GPUBuffer::reuseSubDataBuffer(RetainPtr<MTLBuffer>&& buffer)
-{
- m_subDataBuffers.append(WTFMove(buffer));
-}
#endif // USE(METAL)
void GPUBuffer::registerMappingCallback(MappingCallback&& callback, bool isRead)
@@ -266,16 +220,54 @@
return m_stagingBuffer.get();
}
+void GPUBuffer::copyStagingBufferToGPU()
+{
+ MTLCommandQueue *queue;
+ if (!m_device->tryGetQueue() || !(queue = m_device->tryGetQueue()->platformQueue()))
+ return;
+
+ RetainPtr<MTLBuffer> stagingMtlBuffer;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ // GPUBuffer creation validation ensures m_byteSize fits in NSUInteger.
+ stagingMtlBuffer = adoptNS([m_device->platformDevice() newBufferWithLength:static_cast<NSUInteger>(m_byteLength) options:MTLResourceCPUCacheModeDefaultCache]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ if (!stagingMtlBuffer) {
+ LOG(WebGPU, "GPUBuffer::unmap(): Unable to create staging buffer!");
+ return;
+ }
+
+ memcpy(stagingMtlBuffer.get().contents, m_stagingBuffer->data(), m_byteLength);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ auto commandBuffer = retainPtr([queue commandBuffer]);
+ auto blitEncoder = retainPtr([commandBuffer blitCommandEncoder]);
+
+ [blitEncoder copyFromBuffer:stagingMtlBuffer.get() sourceOffset:0 toBuffer:m_platformBuffer.get() destinationOffset:0 size:static_cast<NSUInteger>(m_byteLength)];
+ [blitEncoder endEncoding];
+ [commandBuffer commit];
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
void GPUBuffer::unmap()
{
- if (!isMappable()) {
- LOG(WebGPU, "GPUBuffer::unmap(): Buffer is not mappable!");
+ if (!m_isMappedFromCreation && !isMappable()) {
+ LOG(WebGPU, "GPUBuffer::unmap(): Invalid operation: buffer is not mappable!");
return;
}
- if (m_stagingBuffer && isMapWrite()) {
- ASSERT(m_platformBuffer);
- memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength);
+ if (m_stagingBuffer) {
+ if (isMappable()) {
+ // MAP_WRITE and MAP_READ buffers have shared, CPU-accessible storage.
+ ASSERT(m_platformBuffer && m_platformBuffer.get().contents);
+ memcpy(m_platformBuffer.get().contents, m_stagingBuffer->data(), m_byteLength);
+ } else if (m_isMappedFromCreation)
+ copyStagingBufferToGPU();
+
+ m_isMappedFromCreation = false;
m_stagingBuffer = nullptr;
}