[WebGPU] WebGPURenderPassEncoder::setPipeline, draw, and endPass prototypes
authorjustin_fan@apple.com <justin_fan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Nov 2018 21:09:08 +0000 (21:09 +0000)
committerjustin_fan@apple.com <justin_fan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Nov 2018 21:09:08 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192134

Reviewed by Dean Jackson.

Source/WebCore:

Wrap up prototype features for WebGPURenderPassEncoder.

Test: webgpu/render-command-encoding.html

* Modules/webgpu/WebGPUCommandBuffer.cpp:
(WebCore::WebGPUCommandBuffer::beginRenderPass):
* Modules/webgpu/WebGPUDevice.cpp:
(WebCore::WebGPUDevice::createRenderPipeline const):
* Modules/webgpu/WebGPUProgrammablePassEncoder.cpp:
(WebCore::WebGPUProgrammablePassEncoder::WebGPUProgrammablePassEncoder):
(WebCore::WebGPUProgrammablePassEncoder::endPass): Returns a reference to the WebGPUCommandBuffer that created this encoder.
(WebCore::WebGPUProgrammablePassEncoder::setPipeline):
* Modules/webgpu/WebGPUProgrammablePassEncoder.h: Updated to support endPass and setPipeline.
* Modules/webgpu/WebGPUProgrammablePassEncoder.idl:
* Modules/webgpu/WebGPURenderPassEncoder.cpp:
(WebCore::WebGPURenderPassEncoder::create): Must be provided with the WebGPUCommandBuffer.
(WebCore::WebGPURenderPassEncoder::WebGPURenderPassEncoder):
(WebCore::WebGPURenderPassEncoder::draw):
* Modules/webgpu/WebGPURenderPassEncoder.h: Updated to cache a reference to the WebGPUCommandBuffer, and for draw.
* Modules/webgpu/WebGPURenderPassEncoder.idl:
* Modules/webgpu/WebGPURenderPipeline.cpp:
(WebCore::WebGPURenderPipeline::create):
(WebCore::WebGPURenderPipeline::WebGPURenderPipeline):
* Modules/webgpu/WebGPURenderPipeline.h:
(WebCore::WebGPURenderPipeline::renderPipeline):
* Modules/webgpu/WebGPUTexture.cpp:
* Modules/webgpu/WebGPUTexture.h: Replaced include with forward declaration.
* platform/graphics/gpu/GPUProgrammablePassEncoder.h: Updated to support new WebGPU_PassEncoder functionality.
* platform/graphics/gpu/GPURenderPassEncoder.h:
(WebCore::GPURenderPassEncoder::~GPURenderPassEncoder): Now ends encoding on the MTLCommandEncoder, if not already ended, before freeing it.
* platform/graphics/gpu/GPURenderPipeline.h: Now remembers the GPUPrimitiveTopology that it was created with.
(WebCore::GPURenderPipeline::primitiveTopology const):
* platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm:
(WebCore::GPUProgrammablePassEncoder::endPass): Calls endEncoding on the backing MTLCommandEncoder, if not already ended.
* platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm:
(WebCore::GPURenderPassEncoder::platformPassEncoder const):
(WebCore::GPURenderPassEncoder::setPipeline): Added.
(WebCore::primitiveTypeForGPUPrimitiveTopology): Added. Helper function to convert GPUPrimitiveTopology to MTLPrimitiveType.
(WebCore::GPURenderPassEncoder::draw): Added. Draws using primitive topology specified during pipeline creation.
* platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm:
(WebCore::setFunctionsForPipelineDescriptor):
(WebCore::GPURenderPipeline::create):
(WebCore::GPURenderPipeline::GPURenderPipeline): Now must store the GPURenderPipelineDescriptor for later reference.

LayoutTests:

Updating the basic rendering test with more commands, and a prototype WPT-based test for WebGPURenderCommandEncoder's
new functionality.

* webgpu/js/basic-webgpu-functions.js:
(render):
* webgpu/render-command-encoding-expected.txt: Added.
* webgpu/render-command-encoding.html: Added.
* webgpu/render-passes.html:

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/webgpu/js/basic-webgpu-functions.js
LayoutTests/webgpu/render-command-encoding-expected.txt [new file with mode: 0644]
LayoutTests/webgpu/render-command-encoding.html [new file with mode: 0644]
LayoutTests/webgpu/render-passes.html
Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WebGPUCommandBuffer.cpp
Source/WebCore/Modules/webgpu/WebGPUDevice.cpp
Source/WebCore/Modules/webgpu/WebGPUProgrammablePassEncoder.cpp
Source/WebCore/Modules/webgpu/WebGPUProgrammablePassEncoder.h
Source/WebCore/Modules/webgpu/WebGPUProgrammablePassEncoder.idl
Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.cpp
Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.h
Source/WebCore/Modules/webgpu/WebGPURenderPassEncoder.idl
Source/WebCore/Modules/webgpu/WebGPURenderPipeline.cpp
Source/WebCore/Modules/webgpu/WebGPURenderPipeline.h
Source/WebCore/Modules/webgpu/WebGPUTexture.cpp
Source/WebCore/Modules/webgpu/WebGPUTexture.h
Source/WebCore/platform/graphics/gpu/GPUProgrammablePassEncoder.h
Source/WebCore/platform/graphics/gpu/GPURenderPassEncoder.h
Source/WebCore/platform/graphics/gpu/GPURenderPipeline.h
Source/WebCore/platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm
Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm
Source/WebCore/platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm

index 32c274e..b3e8dd2 100644 (file)
@@ -1,3 +1,19 @@
+2018-11-29  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] WebGPURenderPassEncoder::setPipeline, draw, and endPass prototypes
+        https://bugs.webkit.org/show_bug.cgi?id=192134
+
+        Reviewed by Dean Jackson.
+
+        Updating the basic rendering test with more commands, and a prototype WPT-based test for WebGPURenderCommandEncoder's
+        new functionality.
+
+        * webgpu/js/basic-webgpu-functions.js:
+        (render):
+        * webgpu/render-command-encoding-expected.txt: Added.
+        * webgpu/render-command-encoding.html: Added.
+        * webgpu/render-passes.html:
+
 2018-11-29  Justin Michaud  <justin_michaud@apple.com>
 
         CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
index 41f5bce..50aa08e 100644 (file)
@@ -149,5 +149,15 @@ function render() {
         return;
     }
 
+    renderPassEncoder.setPipeline(renderPipeline);
+
+    // Note that we didn't attach any buffers - the shader is generating the vertices for us.
+    renderPassEncoder.draw(3, 1, 0, 0);
+    let commandBufferEnd = renderPassEncoder.endPass();
+    if (!commandBufferEnd) {
+        testFailed("Unable to create WebGPUCommandBuffer from WeGPURenderPassEncoder::endPass!");
+        return;
+    }
+
     // FIXME: Rest of rendering commands to follow.
 }
\ No newline at end of file
diff --git a/LayoutTests/webgpu/render-command-encoding-expected.txt b/LayoutTests/webgpu/render-command-encoding-expected.txt
new file mode 100644 (file)
index 0000000..d1d313f
--- /dev/null
@@ -0,0 +1,4 @@
+PASS [object WebGPU] is defined.
+
+PASS WebGPURenderPassEncoder created and successfully ended 
+
diff --git a/LayoutTests/webgpu/render-command-encoding.html b/LayoutTests/webgpu/render-command-encoding.html
new file mode 100644 (file)
index 0000000..5f824dd
--- /dev/null
@@ -0,0 +1,49 @@
+<!DOCTYPE html><!-- webkit-test-runner [ experimental:WebGPUEnabled=true ] -->
+<meta charset=utf-8>
+<title>Get the WebGPUDevice and ask for the WebGPUQueue</title>
+<body>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/js-test-pre.js"></script>
+<script src="js/basic-webgpu-functions.js"></script>
+<script>
+'use strict';
+
+let commandBuffer, renderPassEncoder;
+
+function beginPass() {
+    // FIXME: Flesh out the rest of WebGPURenderPassDescriptor. 
+    // Default a loadOp, storeOp, and clearColor in the implementation for now.
+    const renderPassDescriptor = {
+        attachment : context.getNextTexture().createDefaultTextureView()
+    }
+
+    renderPassEncoder = commandBuffer.beginRenderPass(renderPassDescriptor);
+    assert_true(renderPassEncoder instanceof WebGPURenderPassEncoder, "beginRenderPass returned a WebGPURenderPassEncoder");
+}
+
+function setUpCommandBuffer() {
+    commandBuffer = defaultDevice.createCommandBuffer();
+    assert_true(commandBuffer instanceof WebGPUCommandBuffer, "createCommandBuffer returned a WebGPUCommandBuffer");
+}
+
+function endRenderPass() {
+    renderPassEncoder.setPipeline(renderPipeline);
+
+    const commandBufferEnd = renderPassEncoder.endPass();
+    assert_true(commandBufferEnd instanceof WebGPUCommandBuffer, "endPass() returned a WebGPUCommandBuffer");
+
+    // FIXME: Should commandBufferEnd === commandBuffer?
+}
+
+promise_test(async () => {
+    const canvas = document.createElement("canvas");
+    await setUpContexts(canvas);
+    setUpPipeline();
+    setUpCommandBuffer();
+    beginPass();
+    endRenderPass();
+}, "WebGPURenderPassEncoder created and successfully ended");
+
+</script>
+</body>
index dc94050..286d47a 100644 (file)
@@ -6,16 +6,16 @@
 if (window.testRunner)
     window.testRunner.dumpAsText();
 
-let commandBuffer, texture, textureView, renderPassDescriptor, renderPassEncoder;
+let commandBuffer, renderPassEncoder;
 
 function setUpBasicRenderPassEncoder() {
     commandBuffer = defaultDevice.createCommandBuffer();
-    texture = context.getNextTexture();
-    textureView = texture.createDefaultTextureView();
+    const texture = context.getNextTexture();
+    const textureView = texture.createDefaultTextureView();
 
     // FIXME: Flesh out the rest of WebGPURenderPassDescriptor. 
     // Default a loadOp, storeOp, and clearColor in the implementation for now.
-    renderPassDescriptor = {
+    const renderPassDescriptor = {
         attachment : textureView
     }
 
index 08bc032..e0d9f06 100644 (file)
@@ -1,3 +1,54 @@
+2018-11-29  Justin Fan  <justin_fan@apple.com>
+
+        [WebGPU] WebGPURenderPassEncoder::setPipeline, draw, and endPass prototypes
+        https://bugs.webkit.org/show_bug.cgi?id=192134
+
+        Reviewed by Dean Jackson.
+
+        Wrap up prototype features for WebGPURenderPassEncoder. 
+
+        Test: webgpu/render-command-encoding.html
+
+        * Modules/webgpu/WebGPUCommandBuffer.cpp: 
+        (WebCore::WebGPUCommandBuffer::beginRenderPass):
+        * Modules/webgpu/WebGPUDevice.cpp:
+        (WebCore::WebGPUDevice::createRenderPipeline const):
+        * Modules/webgpu/WebGPUProgrammablePassEncoder.cpp:
+        (WebCore::WebGPUProgrammablePassEncoder::WebGPUProgrammablePassEncoder):
+        (WebCore::WebGPUProgrammablePassEncoder::endPass): Returns a reference to the WebGPUCommandBuffer that created this encoder.
+        (WebCore::WebGPUProgrammablePassEncoder::setPipeline):
+        * Modules/webgpu/WebGPUProgrammablePassEncoder.h: Updated to support endPass and setPipeline.
+        * Modules/webgpu/WebGPUProgrammablePassEncoder.idl:
+        * Modules/webgpu/WebGPURenderPassEncoder.cpp:
+        (WebCore::WebGPURenderPassEncoder::create): Must be provided with the WebGPUCommandBuffer.
+        (WebCore::WebGPURenderPassEncoder::WebGPURenderPassEncoder):
+        (WebCore::WebGPURenderPassEncoder::draw):
+        * Modules/webgpu/WebGPURenderPassEncoder.h: Updated to cache a reference to the WebGPUCommandBuffer, and for draw.
+        * Modules/webgpu/WebGPURenderPassEncoder.idl:
+        * Modules/webgpu/WebGPURenderPipeline.cpp:
+        (WebCore::WebGPURenderPipeline::create):
+        (WebCore::WebGPURenderPipeline::WebGPURenderPipeline):
+        * Modules/webgpu/WebGPURenderPipeline.h:
+        (WebCore::WebGPURenderPipeline::renderPipeline):
+        * Modules/webgpu/WebGPUTexture.cpp:
+        * Modules/webgpu/WebGPUTexture.h: Replaced include with forward declaration.
+        * platform/graphics/gpu/GPUProgrammablePassEncoder.h: Updated to support new WebGPU_PassEncoder functionality.
+        * platform/graphics/gpu/GPURenderPassEncoder.h:
+        (WebCore::GPURenderPassEncoder::~GPURenderPassEncoder): Now ends encoding on the MTLCommandEncoder, if not already ended, before freeing it.
+        * platform/graphics/gpu/GPURenderPipeline.h: Now remembers the GPUPrimitiveTopology that it was created with.
+        (WebCore::GPURenderPipeline::primitiveTopology const): 
+        * platform/graphics/gpu/cocoa/GPUProgrammablePassEncoderMetal.mm:
+        (WebCore::GPUProgrammablePassEncoder::endPass): Calls endEncoding on the backing MTLCommandEncoder, if not already ended.
+        * platform/graphics/gpu/cocoa/GPURenderPassEncoderMetal.mm:
+        (WebCore::GPURenderPassEncoder::platformPassEncoder const):
+        (WebCore::GPURenderPassEncoder::setPipeline): Added.
+        (WebCore::primitiveTypeForGPUPrimitiveTopology): Added. Helper function to convert GPUPrimitiveTopology to MTLPrimitiveType.
+        (WebCore::GPURenderPassEncoder::draw): Added. Draws using primitive topology specified during pipeline creation. 
+        * platform/graphics/gpu/cocoa/GPURenderPipelineMetal.mm:
+        (WebCore::setFunctionsForPipelineDescriptor):
+        (WebCore::GPURenderPipeline::create):
+        (WebCore::GPURenderPipeline::GPURenderPipeline): Now must store the GPURenderPipelineDescriptor for later reference. 
+
 2018-11-29  Justin Michaud  <justin_michaud@apple.com>
 
         CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change.
index 53fa1de..4f76046 100644 (file)
@@ -63,7 +63,7 @@ RefPtr<WebGPURenderPassEncoder> WebGPUCommandBuffer::beginRenderPass(WebGPURende
     if (!encoder)
         return nullptr;
 
-    return WebGPURenderPassEncoder::create(encoder.releaseNonNull());
+    return WebGPURenderPassEncoder::create(*this, encoder.releaseNonNull());
 }
 
 } // namespace WebCore
index e901c12..53d1392 100644 (file)
@@ -117,7 +117,12 @@ RefPtr<WebGPURenderPipeline> WebGPUDevice::createRenderPipeline(WebGPURenderPipe
         return nullptr;
     }
 
-    return WebGPURenderPipeline::create(m_device->createRenderPipeline(GPURenderPipelineDescriptor { WTFMove(vertexStage), WTFMove(fragmentStage), descriptor.primitiveTopology }));
+    auto pipeline = m_device->createRenderPipeline(GPURenderPipelineDescriptor { WTFMove(vertexStage), WTFMove(fragmentStage), descriptor.primitiveTopology });
+
+    if (!pipeline)
+        return nullptr;
+
+    return WebGPURenderPipeline::create(pipeline.releaseNonNull());
 }
 
 RefPtr<WebGPUCommandBuffer> WebGPUDevice::createCommandBuffer() const
index 5851578..89282b5 100644 (file)
 
 #if ENABLE(WEBGPU)
 
+#include "GPUProgrammablePassEncoder.h"
+#include "WebGPUCommandBuffer.h"
+#include "WebGPURenderPipeline.h"
+
 namespace WebCore {
 
+WebGPUProgrammablePassEncoder::WebGPUProgrammablePassEncoder(Ref<WebGPUCommandBuffer>&& creator)
+    : m_commandBuffer(WTFMove(creator))
+{
+}
+
+Ref<WebGPUCommandBuffer> WebGPUProgrammablePassEncoder::endPass()
+{
+    passEncoder().endPass();
+    return m_commandBuffer.copyRef();
+}
+
+void WebGPUProgrammablePassEncoder::setPipeline(Ref<WebGPURenderPipeline>&& pipeline)
+{
+    passEncoder().setPipeline(pipeline->renderPipeline());
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEBGPU)
index e73e7d0..638484b 100644 (file)
 namespace WebCore {
 
 class GPUProgrammablePassEncoder;
+class WebGPUCommandBuffer;
+class WebGPURenderPipeline;
 
 class WebGPUProgrammablePassEncoder : public RefCounted<WebGPUProgrammablePassEncoder> {
 public:
     virtual ~WebGPUProgrammablePassEncoder() = default;
 
+    Ref<WebGPUCommandBuffer> endPass();
+    void setPipeline(Ref<WebGPURenderPipeline>&&);
+
 protected:
+    WebGPUProgrammablePassEncoder(Ref<WebGPUCommandBuffer>&&);
+
     virtual GPUProgrammablePassEncoder& passEncoder() const = 0;
+
+private:
+    Ref<WebGPUCommandBuffer> m_commandBuffer;
 };
 
 } // namespace WebCore
index 69ca850..35361d9 100644 (file)
     EnabledAtRuntime=WebGPU,
     SkipVTableValidation
 ] interface WebGPUProgrammablePassEncoder {
-/* Not Yet Implemented
     WebGPUCommandBuffer endPass();
+
+    // FIXME: Only support render pipelines for prototype.
+    void setPipeline(WebGPURenderPipeline pipeline);
+/* Not Yet Implemented
     // Allowed in both compute and render passes
     // TODO: setPushConstants() ?
     void setBindGroup(u32 index, WebGPUBindGroup bindGroup);
-    void setPipeline((WebGPUComputePipeline or WebGPURenderPipeline) pipeline);
 */
 };
index 3dd169b..8eb0b46 100644 (file)
 #if ENABLE(WEBGPU)
 
 #include "GPUProgrammablePassEncoder.h"
+#include "GPURenderPassEncoder.h"
 
 namespace WebCore {
 
-Ref<WebGPURenderPassEncoder> WebGPURenderPassEncoder::create(Ref<GPURenderPassEncoder>&& encoder)
+Ref<WebGPURenderPassEncoder> WebGPURenderPassEncoder::create(Ref<WebGPUCommandBuffer>&& creator, Ref<GPURenderPassEncoder>&& encoder)
 {
-    return adoptRef(*new WebGPURenderPassEncoder(WTFMove(encoder)));
+    return adoptRef(*new WebGPURenderPassEncoder(WTFMove(creator), WTFMove(encoder)));
 }
 
-WebGPURenderPassEncoder::WebGPURenderPassEncoder(Ref<GPURenderPassEncoder>&& encoder)
-    : m_passEncoder(WTFMove(encoder))
+WebGPURenderPassEncoder::WebGPURenderPassEncoder(Ref<WebGPUCommandBuffer>&& creator, Ref<GPURenderPassEncoder>&& encoder)
+    : WebGPUProgrammablePassEncoder(WTFMove(creator))
+    , m_passEncoder(WTFMove(encoder))
 {
 }
 
+void WebGPURenderPassEncoder::draw(unsigned long vertexCount, unsigned long instanceCount, unsigned long firstVertex, unsigned long firstInstance)
+{
+    // FIXME: What kind of validation do we need to handle here?
+    m_passEncoder->draw(vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
 GPUProgrammablePassEncoder& WebGPURenderPassEncoder::passEncoder() const
 {
     return m_passEncoder.get();
index 407c675..c74da7a 100644 (file)
@@ -27,7 +27,6 @@
 
 #if ENABLE(WEBGPU)
 
-#include "GPURenderPassEncoder.h"
 #include "WebGPUProgrammablePassEncoder.h"
 
 #include <wtf/RefPtr.h>
 namespace WebCore {
 
 class GPUProgrammablePassEncoder;
+class GPURenderPassEncoder;
 
 class WebGPURenderPassEncoder final : public WebGPUProgrammablePassEncoder {
 public:
-    static Ref<WebGPURenderPassEncoder> create(Ref<GPURenderPassEncoder>&&);
+    static Ref<WebGPURenderPassEncoder> create(Ref<WebGPUCommandBuffer>&&, Ref<GPURenderPassEncoder>&&);
+
+    void draw(unsigned long, unsigned long, unsigned long, unsigned long);
 
 private:
-    WebGPURenderPassEncoder(Ref<GPURenderPassEncoder>&&);
+    WebGPURenderPassEncoder(Ref<WebGPUCommandBuffer>&&, Ref<GPURenderPassEncoder>&&);
 
     GPUProgrammablePassEncoder& passEncoder() const final;
 
index 5000d3d..868f68f 100644 (file)
  */
 // https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl
 
+typedef unsigned long u32;
+
 [
     Conditional=WEBGPU,
-    EnabledAtRuntime=WebGPU
+    EnabledAtRuntime=WebGPU,
+    JSGenerateToJSObject
 ] interface WebGPURenderPassEncoder : WebGPUProgrammablePassEncoder {
+    void draw(u32 vertexCount, u32 instanceCount, u32 firstVertex, u32 firstInstance);
+
 /* Not Yet Implemented
     void setBlendColor(float r, float g, float b, float a);
     void setIndexBuffer(WebGPUBuffer buffer, u32 offset);
     void setVertexBuffers(u32 startSlot, sequence<WebGPUBuffer> buffers, sequence<u32> offsets);
 
-    void draw(u32 vertexCount, u32 instanceCount, u32 firstVertex, u32 firstInstance);
     void drawIndexed(u32 indexCount, u32 instanceCount, u32 firstIndex, i32 baseVertex, u32 firstInstance);
 
     // TODO add missing commands
index ab3c020..3ccf3c0 100644 (file)
 
 namespace WebCore {
 
-RefPtr<WebGPURenderPipeline> WebGPURenderPipeline::create(RefPtr<GPURenderPipeline>&& pipeline)
+RefPtr<WebGPURenderPipeline> WebGPURenderPipeline::create(Ref<GPURenderPipeline>&& pipeline)
 {
-    if (!pipeline)
-        return nullptr;
-
     return adoptRef(new WebGPURenderPipeline(WTFMove(pipeline)));
 }
 
-WebGPURenderPipeline::WebGPURenderPipeline(RefPtr<GPURenderPipeline>&& pipeline)
-    : m_renderPipeline(pipeline)
+WebGPURenderPipeline::WebGPURenderPipeline(Ref<GPURenderPipeline>&& pipeline)
+    : m_renderPipeline(WTFMove(pipeline))
 {
     UNUSED_PARAM(m_renderPipeline);
 }
index 8b51062..2c8b866 100644 (file)
@@ -36,12 +36,14 @@ namespace WebCore {
 
 class WebGPURenderPipeline : public RefCounted<WebGPURenderPipeline> {
 public:
-    static RefPtr<WebGPURenderPipeline> create(RefPtr<GPURenderPipeline>&&);
+    static RefPtr<WebGPURenderPipeline> create(Ref<GPURenderPipeline>&&);
+
+    Ref<GPURenderPipeline> renderPipeline() { return m_renderPipeline.copyRef(); }
 
 private:
-    WebGPURenderPipeline(RefPtr<GPURenderPipeline>&&);
+    WebGPURenderPipeline(Ref<GPURenderPipeline>&&);
 
-    RefPtr<GPURenderPipeline> m_renderPipeline;
+    Ref<GPURenderPipeline> m_renderPipeline;
 };
 
 } // namespace WebCore
index d5b4b3b..ee1f243 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(WEBGPU)
 
+#include "GPUTexture.h"
 #include "WebGPUTextureView.h"
 
 namespace WebCore {
index 11c08de..1d44a39 100644 (file)
 
 #if ENABLE(WEBGPU)
 
-#include "GPUTexture.h"
-
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
 
+class GPUTexture;
 class WebGPUTextureView;
 
 class WebGPUTexture : public RefCounted<WebGPUTexture> {
index 95bb4b5..948c0c8 100644 (file)
@@ -33,14 +33,23 @@ OBJC_PROTOCOL(MTLCommandEncoder);
 
 namespace WebCore {
 
+class GPURenderPipeline;
+
 using PlatformProgrammablePassEncoder = MTLCommandEncoder;
 
 class GPUProgrammablePassEncoder : public RefCounted<GPUProgrammablePassEncoder> {
 public:
     virtual ~GPUProgrammablePassEncoder() = default;
 
+    void endPass();
+
+    virtual void setPipeline(Ref<GPURenderPipeline>&&) = 0;
+
 protected:
     virtual PlatformProgrammablePassEncoder* platformPassEncoder() const = 0;
+
+private:
+    bool m_isEncoding { true };
 };
 
 } // namespace WebCore
index f404478..3b64d04 100644 (file)
@@ -38,6 +38,7 @@ OBJC_PROTOCOL(MTLRenderCommandEncoder);
 namespace WebCore {
 
 class GPUCommandBuffer;
+class GPURenderPipeline;
 
 struct GPURenderPassDescriptor;
 
@@ -48,13 +49,18 @@ class GPURenderPassEncoder : public GPUProgrammablePassEncoder {
 public:
     static RefPtr<GPURenderPassEncoder> create(const GPUCommandBuffer&, GPURenderPassDescriptor&&);
 
+    void setPipeline(Ref<GPURenderPipeline>&&) final;
+
+    void draw(unsigned long, unsigned long, unsigned long, unsigned long);
+
 private:
     GPURenderPassEncoder(PlatformRenderPassEncoderSmartPtr&&);
-    ~GPURenderPassEncoder();
+    ~GPURenderPassEncoder() { endPass(); } // Ensure that encoding has ended before release.
 
-    PlatformProgrammablePassEncoder *platformPassEncoder() const final;
+    PlatformProgrammablePassEncoderplatformPassEncoder() const final;
 
     PlatformRenderPassEncoderSmartPtr m_platformRenderPassEncoder;
+    RefPtr<GPURenderPipeline> m_pipeline;
 };
 
 } // namespace WebCore
index 42fd9a3..b3b5484 100644 (file)
@@ -27,6 +27,8 @@
 
 #if ENABLE(WEBGPU)
 
+#include "GPURenderPipelineDescriptor.h"
+
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/RetainPtr.h>
@@ -37,10 +39,9 @@ namespace WebCore {
 
 class GPUDevice;
 
-struct GPURenderPipelineDescriptor;
-
 using PlatformRenderPipeline = MTLRenderPipelineState;
 using PlatformRenderPipelineSmartPtr = RetainPtr<MTLRenderPipelineState>;
+using PrimitiveTopology = GPURenderPipelineDescriptor::PrimitiveTopology;
 
 class GPURenderPipeline : public RefCounted<GPURenderPipeline> {
 public:
@@ -48,10 +49,13 @@ public:
 
     PlatformRenderPipeline* platformRenderPipeline() const { return m_platformRenderPipeline.get(); }
 
+    PrimitiveTopology primitiveTopology() const { return m_descriptor.primitiveTopology; }
+
 private:
-    GPURenderPipeline(PlatformRenderPipelineSmartPtr&&);
+    GPURenderPipeline(PlatformRenderPipelineSmartPtr&&, GPURenderPipelineDescriptor&&);
 
     PlatformRenderPipelineSmartPtr m_platformRenderPipeline;
+    GPURenderPipelineDescriptor m_descriptor;
 };
 
 } // namespace WebCore
index 0bb428f..2e64363 100644 (file)
 
 #if ENABLE(WEBGPU)
 
+#import <Metal/Metal.h>
+
 namespace WebCore {
 
+void GPUProgrammablePassEncoder::endPass()
+{
+    if (!m_isEncoding)
+        return;
+
+    [platformPassEncoder() endEncoding];
+    m_isEncoding = false;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEBGPU)
index e01a883..38adb86 100644 (file)
@@ -30,6 +30,7 @@
 
 #import "GPUCommandBuffer.h"
 #import "GPURenderPassDescriptor.h"
+#import "GPURenderPipeline.h"
 #import "Logging.h"
 
 #import <Metal/Metal.h>
@@ -68,16 +69,41 @@ GPURenderPassEncoder::GPURenderPassEncoder(PlatformRenderPassEncoderSmartPtr&& e
 {
 }
 
-GPURenderPassEncoder::~GPURenderPassEncoder()
+PlatformProgrammablePassEncoder *GPURenderPassEncoder::platformPassEncoder() const
 {
-    // The MTLCommandEncoder must have finished encoding before it can be released.
-    // FIXME: Only call this if we have not already ended encoding.
-    [m_platformRenderPassEncoder endEncoding];
+    return m_platformRenderPassEncoder.get();
 }
 
-PlatformProgrammablePassEncoder *GPURenderPassEncoder::platformPassEncoder() const
+void GPURenderPassEncoder::setPipeline(Ref<GPURenderPipeline>&& pipeline)
 {
-    return m_platformRenderPassEncoder.get();
+    [m_platformRenderPassEncoder setRenderPipelineState:pipeline->platformRenderPipeline()];
+    m_pipeline = WTFMove(pipeline);
+}
+
+static MTLPrimitiveType primitiveTypeForGPUPrimitiveTopology(PrimitiveTopology type)
+{
+    switch (type) {
+    case PrimitiveTopology::PointList:
+        return MTLPrimitiveTypePoint;
+    case PrimitiveTopology::LineList:
+        return MTLPrimitiveTypeLine;
+    case PrimitiveTopology::LineStrip:
+        return MTLPrimitiveTypeLineStrip;
+    case PrimitiveTopology::TriangleList:
+        return MTLPrimitiveTypeTriangle;
+    case PrimitiveTopology::TriangleStrip:
+        return MTLPrimitiveTypeTriangleStrip;
+    }
+}
+
+void GPURenderPassEncoder::draw(unsigned long vertexCount, unsigned long instanceCount, unsigned long firstVertex, unsigned long firstInstance)
+{
+    [m_platformRenderPassEncoder 
+        drawPrimitives:primitiveTypeForGPUPrimitiveTopology(m_pipeline->primitiveTopology())
+        vertexStart:firstVertex
+        vertexCount:vertexCount
+        instanceCount:instanceCount
+        baseInstance:firstInstance];
 }
 
 } // namespace WebCore
index c946d55..9eca4c1 100644 (file)
@@ -28,7 +28,6 @@
 
 #if ENABLE(WEBGPU)
 
-#import "GPURenderPipelineDescriptor.h"
 #import "Logging.h"
 
 #import <Metal/Metal.h>
@@ -36,7 +35,7 @@
 
 namespace WebCore {
 
-static bool setFunctionsForPipelineDescriptor(const char* const functionName, MTLRenderPipelineDescriptor *mtlDescriptor, GPURenderPipelineDescriptor&& descriptor)
+static bool setFunctionsForPipelineDescriptor(const char* const functionName, MTLRenderPipelineDescriptor *mtlDescriptor, const GPURenderPipelineDescriptor& descriptor)
 {
 #if LOG_DISABLED
     UNUSED_PARAM(functionName);
@@ -105,7 +104,7 @@ RefPtr<GPURenderPipeline> GPURenderPipeline::create(const GPUDevice& device, GPU
         return nullptr;
     }
 
-    if (!setFunctionsForPipelineDescriptor(functionName, mtlDescriptor.get(), WTFMove(descriptor)))
+    if (!setFunctionsForPipelineDescriptor(functionName, mtlDescriptor.get(), descriptor))
         return nullptr;
 
     // FIXME: Get the pixelFormat as configured for the context/CAMetalLayer.
@@ -124,11 +123,12 @@ RefPtr<GPURenderPipeline> GPURenderPipeline::create(const GPUDevice& device, GPU
         return nullptr;
     }
 
-    return adoptRef(new GPURenderPipeline(WTFMove(pipeline)));
+    return adoptRef(new GPURenderPipeline(WTFMove(pipeline), WTFMove(descriptor)));
 }
 
-GPURenderPipeline::GPURenderPipeline(PlatformRenderPipelineSmartPtr&& pipeline)
+GPURenderPipeline::GPURenderPipeline(PlatformRenderPipelineSmartPtr&& pipeline, GPURenderPipelineDescriptor&& descriptor)
     : m_platformRenderPipeline(WTFMove(pipeline))
+    , m_descriptor(WTFMove(descriptor))
 {
 }