Title: [291372] trunk/Source/WebGPU
Revision
291372
Author
[email protected]
Date
2022-03-16 15:13:40 -0700 (Wed, 16 Mar 2022)

Log Message

[WebGPU] Implement first draft of buffer copying according to the spec
https://bugs.webkit.org/show_bug.cgi?id=237871

Reviewed by Kimmo Kinnunen.

Implement CommandEncoder::copyBufferToBuffer() and CommandEncoder::finish(),
according to the algorithms in the spec. There are a few things which the spec
lists which we can't do yet (like reporting validation errors), so those things
are left with FIXMEs. Every step is listed with links to the spec where
appropriate, and with quotes to the spec describing what is being implemented.

* WebGPU.xcodeproj/project.pbxproj:
* WebGPU/CommandEncoder.h:
* WebGPU/CommandEncoder.mm:
(WebGPU::Device::createCommandEncoder):
(WebGPU::CommandEncoder::ensureBlitCommandEncoder):
(WebGPU::CommandEncoder::finalizeBlitCommandEncoder):
(WebGPU::validateCopyBufferToBuffer):
(WebGPU::CommandEncoder::copyBufferToBuffer):
(WebGPU::CommandEncoder::validateFinish const):
(WebGPU::CommandEncoder::finish):
* WebGPU/CommandsMixin.h: Added.
* WebGPU/CommandsMixin.mm: Added.
(WebGPU::CommandsMixin::prepareTheEncoderState const):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebGPU/ChangeLog (291371 => 291372)


--- trunk/Source/WebGPU/ChangeLog	2022-03-16 21:58:52 UTC (rev 291371)
+++ trunk/Source/WebGPU/ChangeLog	2022-03-16 22:13:40 UTC (rev 291372)
@@ -1,5 +1,32 @@
 2022-03-16  Myles C. Maxfield  <[email protected]>
 
+        [WebGPU] Implement first draft of buffer copying according to the spec
+        https://bugs.webkit.org/show_bug.cgi?id=237871
+
+        Reviewed by Kimmo Kinnunen.
+
+        Implement CommandEncoder::copyBufferToBuffer() and CommandEncoder::finish(),
+        according to the algorithms in the spec. There are a few things which the spec
+        lists which we can't do yet (like reporting validation errors), so those things
+        are left with FIXMEs. Every step is listed with links to the spec where
+        appropriate, and with quotes to the spec describing what is being implemented.
+
+        * WebGPU.xcodeproj/project.pbxproj:
+        * WebGPU/CommandEncoder.h:
+        * WebGPU/CommandEncoder.mm:
+        (WebGPU::Device::createCommandEncoder):
+        (WebGPU::CommandEncoder::ensureBlitCommandEncoder):
+        (WebGPU::CommandEncoder::finalizeBlitCommandEncoder):
+        (WebGPU::validateCopyBufferToBuffer):
+        (WebGPU::CommandEncoder::copyBufferToBuffer):
+        (WebGPU::CommandEncoder::validateFinish const):
+        (WebGPU::CommandEncoder::finish):
+        * WebGPU/CommandsMixin.h: Added.
+        * WebGPU/CommandsMixin.mm: Added.
+        (WebGPU::CommandsMixin::prepareTheEncoderState const):
+
+2022-03-16  Myles C. Maxfield  <[email protected]>
+
         [WebGPU] Implement first draft of buffer mapping according to the spec
         https://bugs.webkit.org/show_bug.cgi?id=237870
 

Modified: trunk/Source/WebGPU/WebGPU/CommandEncoder.h (291371 => 291372)


--- trunk/Source/WebGPU/WebGPU/CommandEncoder.h	2022-03-16 21:58:52 UTC (rev 291371)
+++ trunk/Source/WebGPU/WebGPU/CommandEncoder.h	2022-03-16 22:13:40 UTC (rev 291372)
@@ -25,9 +25,9 @@
 
 #pragma once
 
+#import "CommandsMixin.h"
 #import <wtf/FastMalloc.h>
 #import <wtf/Ref.h>
-#import <wtf/RefCounted.h>
 #import <wtf/RefPtr.h>
 
 namespace WebGPU {
@@ -38,7 +38,7 @@
 class QuerySet;
 class RenderPassEncoder;
 
-class CommandEncoder : public RefCounted<CommandEncoder> {
+class CommandEncoder : public RefCounted<CommandEncoder>, public CommandsMixin {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     static Ref<CommandEncoder> create(id<MTLCommandBuffer> commandBuffer)
@@ -66,7 +66,13 @@
 private:
     CommandEncoder(id<MTLCommandBuffer>);
 
+    bool validateFinish() const;
+
+    void ensureBlitCommandEncoder();
+    void finalizeBlitCommandEncoder();
+
     id<MTLCommandBuffer> m_commandBuffer { nil };
+    id<MTLBlitCommandEncoder> m_blitCommandEncoder { nil };
 };
 
 } // namespace WebGPU

Modified: trunk/Source/WebGPU/WebGPU/CommandEncoder.mm (291371 => 291372)


--- trunk/Source/WebGPU/WebGPU/CommandEncoder.mm	2022-03-16 21:58:52 UTC (rev 291371)
+++ trunk/Source/WebGPU/WebGPU/CommandEncoder.mm	2022-03-16 22:13:40 UTC (rev 291372)
@@ -32,13 +32,26 @@
 #import "Device.h"
 #import "QuerySet.h"
 #import "RenderPassEncoder.h"
+#import "Utilities.h"
 
 namespace WebGPU {
 
 RefPtr<CommandEncoder> Device::createCommandEncoder(const WGPUCommandEncoderDescriptor& descriptor)
 {
-    UNUSED_PARAM(descriptor);
-    return CommandEncoder::create(nil);
+    if (descriptor.nextInChain)
+        return nullptr;
+
+    // https://gpuweb.github.io/gpuweb/#dom-gpudevice-createcommandencoder
+
+    auto *commandBufferDescriptor = [MTLCommandBufferDescriptor new];
+    commandBufferDescriptor.errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus;
+    id<MTLCommandBuffer> commandBuffer = [getQueue().commandQueue() commandBufferWithDescriptor:commandBufferDescriptor];
+    if (!commandBuffer)
+        return nullptr;
+
+    commandBuffer.label = [NSString stringWithCString:descriptor.label encoding:NSUTF8StringEncoding];
+
+    return CommandEncoder::create(commandBuffer);
 }
 
 CommandEncoder::CommandEncoder(id<MTLCommandBuffer> commandBuffer)
@@ -48,6 +61,18 @@
 
 CommandEncoder::~CommandEncoder() = default;
 
+void CommandEncoder::ensureBlitCommandEncoder()
+{
+    if (!m_blitCommandEncoder)
+        m_blitCommandEncoder = [m_commandBuffer blitCommandEncoder];
+}
+
+void CommandEncoder::finalizeBlitCommandEncoder()
+{
+    if (m_blitCommandEncoder)
+        [m_blitCommandEncoder endEncoding];
+}
+
 RefPtr<ComputePassEncoder> CommandEncoder::beginComputePass(const WGPUComputePassDescriptor& descriptor)
 {
     UNUSED_PARAM(descriptor);
@@ -60,13 +85,70 @@
     return RenderPassEncoder::create(nil);
 }
 
+static bool validateCopyBufferToBuffer(const Buffer& source, uint64_t sourceOffset, const Buffer& destination, uint64_t destinationOffset, uint64_t size)
+{
+    // FIXME: "source is valid to use with this."
+
+    // FIXME: "destination is valid to use with this."
+
+    // "source.[[usage]] contains COPY_SRC."
+    if (!(source.usage() & WGPUBufferUsage_CopySrc))
+        return false;
+
+    // "destination.[[usage]] contains COPY_DST."
+    if (!(destination.usage() & WGPUBufferUsage_CopyDst))
+        return false;
+
+    // "size is a multiple of 4."
+    if (size % 4)
+        return false;
+
+    // "sourceOffset is a multiple of 4."
+    if (sourceOffset % 4)
+        return false;
+
+    // "destinationOffset is a multiple of 4."
+    if (destinationOffset % 4)
+        return false;
+
+    // FIXME: "(sourceOffset + size) does not overflow a GPUSize64."
+
+    // FIXME: "(destinationOffset + size) does not overflow a GPUSize64."
+
+    // FIXME: "source.[[size]] is greater than or equal to (sourceOffset + size)."
+    // FIXME: Use checked arithmetic
+    if (source.size() < sourceOffset + size)
+        return false;
+
+    // FIXME: "destination.[[size]] is greater than or equal to (destinationOffset + size)."
+    // FIXME: Use checked arithmetic
+    if (destination.size() < destinationOffset + size)
+        return false;
+
+    // FIXME: "source and destination are not the same GPUBuffer."
+    if (&source == &destination)
+        return false;
+
+    return true;
+}
+
 void CommandEncoder::copyBufferToBuffer(const Buffer& source, uint64_t sourceOffset, const Buffer& destination, uint64_t destinationOffset, uint64_t size)
 {
-    UNUSED_PARAM(source);
-    UNUSED_PARAM(sourceOffset);
-    UNUSED_PARAM(destination);
-    UNUSED_PARAM(destinationOffset);
-    UNUSED_PARAM(size);
+    // https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-copybuffertobuffer
+
+    // "Prepare the encoder state of this. If it returns false, stop."
+    if (!prepareTheEncoderState())
+        return;
+
+    // "If any of the following conditions are unsatisfied
+    if (!validateCopyBufferToBuffer(source, sourceOffset, destination, destinationOffset, size)) {
+        // FIXME: "generate a validation error and stop."
+        return;
+    }
+
+    ensureBlitCommandEncoder();
+
+    [m_blitCommandEncoder copyFromBuffer:source.buffer() sourceOffset:static_cast<NSUInteger>(sourceOffset) toBuffer:destination.buffer() destinationOffset:destinationOffset size:size];
 }
 
 void CommandEncoder::copyBufferToTexture(const WGPUImageCopyBuffer& source, const WGPUImageCopyTexture& destination, const WGPUExtent3D& copySize)
@@ -97,10 +179,53 @@
     UNUSED_PARAM(size);
 }
 
+bool CommandEncoder::validateFinish() const
+{
+    // "Let validationSucceeded be true if all of the following requirements are met, and false otherwise."
+
+    // FIXME: "this must be valid."
+
+    // "this.[[state]] must be "open"."
+    if (m_state != EncoderState::Open)
+        return false;
+
+    // FIXME: "this.[[debug_group_stack]] must be empty."
+
+    // FIXME: "Every usage scope contained in this must satisfy the usage scope validation."
+
+    return true;
+}
+
 RefPtr<CommandBuffer> CommandEncoder::finish(const WGPUCommandBufferDescriptor& descriptor)
 {
-    UNUSED_PARAM(descriptor);
-    return CommandBuffer::create(nil);
+    if (descriptor.nextInChain)
+        return nullptr;
+
+    // https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-finish
+
+    // "Let validationSucceeded be true if all of the following requirements are met, and false otherwise."
+    auto validationFailed = !validateFinish();
+
+    // "Set this.[[state]] to "ended"."
+    m_state = EncoderState::Ended;
+
+    // "If validationSucceeded is false, then:"
+    if (validationFailed) {
+        // FIXME: "Generate a validation error."
+
+        // FIXME: "Return a new invalid GPUCommandBuffer."
+        return nullptr;
+    }
+
+    finalizeBlitCommandEncoder();
+
+    // "Set commandBuffer.[[command_list]] to this.[[commands]]."
+    auto *commandBuffer = m_commandBuffer;
+    m_commandBuffer = nil;
+
+    commandBuffer.label = [NSString stringWithCString:descriptor.label encoding:NSUTF8StringEncoding];
+
+    return CommandBuffer::create(commandBuffer);
 }
 
 void CommandEncoder::insertDebugMarker(const char* markerLabel)

Added: trunk/Source/WebGPU/WebGPU/CommandsMixin.h (0 => 291372)


--- trunk/Source/WebGPU/WebGPU/CommandsMixin.h	                        (rev 0)
+++ trunk/Source/WebGPU/WebGPU/CommandsMixin.h	2022-03-16 22:13:40 UTC (rev 291372)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 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. ``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
+ * 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
+
+#import <wtf/RefCounted.h>
+
+namespace WebGPU {
+
+class CommandsMixin {
+protected:
+    bool prepareTheEncoderState() const;
+
+    enum class EncoderState : uint8_t {
+        Open,
+        Locked,
+        Ended
+    };
+    EncoderState m_state { EncoderState::Open };
+};
+
+} // namespace WebGPU

Added: trunk/Source/WebGPU/WebGPU/CommandsMixin.mm (0 => 291372)


--- trunk/Source/WebGPU/WebGPU/CommandsMixin.mm	                        (rev 0)
+++ trunk/Source/WebGPU/WebGPU/CommandsMixin.mm	2022-03-16 22:13:40 UTC (rev 291372)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021-2022 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. ``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
+ * 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.
+ */
+
+#import "config.h"
+#import "CommandsMixin.h"
+
+namespace WebGPU {
+
+bool CommandsMixin::prepareTheEncoderState() const
+{
+    // https://gpuweb.github.io/gpuweb/#abstract-opdef-prepare-the-encoder-state
+
+    switch (m_state) {
+    case EncoderState::Open:
+        return true;
+    case EncoderState::Locked:
+        // FIXME: "Make encoder invalid"
+        return false;
+    case EncoderState::Ended:
+        // FIXME: "Generate a validation error"
+        return false;
+    }
+}
+
+} // namespace WebGPU

Modified: trunk/Source/WebGPU/WebGPU.xcodeproj/project.pbxproj (291371 => 291372)


--- trunk/Source/WebGPU/WebGPU.xcodeproj/project.pbxproj	2022-03-16 21:58:52 UTC (rev 291371)
+++ trunk/Source/WebGPU/WebGPU.xcodeproj/project.pbxproj	2022-03-16 22:13:40 UTC (rev 291372)
@@ -13,6 +13,8 @@
 		1C2CEDEE271E8A7300EDC16F /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C2CEDED271E8A7300EDC16F /* Metal.framework */; };
 		1C5319C027BDC6CC00CD127E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5319BF27BDC6CC00CD127E /* main.swift */; };
 		1C5319C527BDC72700CD127E /* WebGPU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CEBD7E32716AFBA00A5254D /* WebGPU.framework */; };
+		1C582FF927E04131009B40F0 /* CommandsMixin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C582FF727E04131009B40F0 /* CommandsMixin.mm */; };
+		1C582FFA27E04131009B40F0 /* CommandsMixin.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C582FF827E04131009B40F0 /* CommandsMixin.h */; };
 		1C5ACA94273A41C20095F8D5 /* Instance.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C5ACA92273A41C20095F8D5 /* Instance.mm */; };
 		1C5ACAB6273A426D0095F8D5 /* RenderPipeline.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C5ACA98273A426D0095F8D5 /* RenderPipeline.mm */; };
 		1C5ACABB273A426D0095F8D5 /* Buffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C5ACA9D273A426D0095F8D5 /* Buffer.mm */; };
@@ -133,6 +135,8 @@
 		1C5319BD27BDC6CB00CD127E /* CommandLinePlayground */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CommandLinePlayground; sourceTree = BUILT_PRODUCTS_DIR; };
 		1C5319BF27BDC6CC00CD127E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
 		1C5319CA27BDD70000CD127E /* CommandLinePlayground.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = CommandLinePlayground.xcconfig; sourceTree = "<group>"; };
+		1C582FF727E04131009B40F0 /* CommandsMixin.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CommandsMixin.mm; sourceTree = "<group>"; };
+		1C582FF827E04131009B40F0 /* CommandsMixin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommandsMixin.h; sourceTree = "<group>"; };
 		1C5ACA92273A41C20095F8D5 /* Instance.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Instance.mm; sourceTree = "<group>"; };
 		1C5ACA96273A426D0095F8D5 /* Surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Surface.h; sourceTree = "<group>"; };
 		1C5ACA97273A426D0095F8D5 /* SwapChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwapChain.h; sourceTree = "<group>"; };
@@ -334,6 +338,8 @@
 				1C5ACAE2273A55CD0095F8D5 /* CommandBuffer.mm */,
 				1C5ACA9E273A426D0095F8D5 /* CommandEncoder.h */,
 				1C5ACAAB273A426D0095F8D5 /* CommandEncoder.mm */,
+				1C582FF827E04131009B40F0 /* CommandsMixin.h */,
+				1C582FF727E04131009B40F0 /* CommandsMixin.mm */,
 				1C5ACAAA273A426D0095F8D5 /* ComputePassEncoder.h */,
 				1C5ACAA8273A426D0095F8D5 /* ComputePassEncoder.mm */,
 				1C5ACAA7273A426D0095F8D5 /* ComputePipeline.h */,
@@ -476,6 +482,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				1C5ACAD7273A4D700095F8D5 /* BindGroup.h in Headers */,
+				1C582FFA27E04131009B40F0 /* CommandsMixin.h in Headers */,
 				1CEBD7E72716AFBA00A5254D /* WebGPU.h in Headers */,
 				1C5ACAD3273A4C860095F8D5 /* WebGPUExt.h in Headers */,
 			);
@@ -722,6 +729,7 @@
 				1C5ACABB273A426D0095F8D5 /* Buffer.mm in Sources */,
 				1C5ACAE3273A55CD0095F8D5 /* CommandBuffer.mm in Sources */,
 				1C5ACAC9273A426E0095F8D5 /* CommandEncoder.mm in Sources */,
+				1C582FF927E04131009B40F0 /* CommandsMixin.mm in Sources */,
 				1C5ACAC6273A426D0095F8D5 /* ComputePassEncoder.mm in Sources */,
 				1C5ACAC0273A426D0095F8D5 /* ComputePipeline.mm in Sources */,
 				1C5ACAC1273A426D0095F8D5 /* Device.mm in Sources */,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to