[WebGPU] Buffer updates part 1: async mapping functions, unmap, and destroy
[WebKit-https.git] / Source / WebCore / Modules / webgpu / WebGPUDevice.cpp
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebGPUDevice.h"
28
29 #if ENABLE(WEBGPU)
30
31 #include "GPUBindGroup.h"
32 #include "GPUBindGroupBinding.h"
33 #include "GPUBindGroupDescriptor.h"
34 #include "GPUBufferBinding.h"
35 #include "GPUBufferDescriptor.h"
36 #include "GPUCommandBuffer.h"
37 #include "GPUPipelineStageDescriptor.h"
38 #include "GPURenderPipelineDescriptor.h"
39 #include "GPUShaderModuleDescriptor.h"
40 #include "GPUTextureDescriptor.h"
41 #include "Logging.h"
42 #include "WebGPUBindGroup.h"
43 #include "WebGPUBindGroupBinding.h"
44 #include "WebGPUBindGroupDescriptor.h"
45 #include "WebGPUBindGroupLayout.h"
46 #include "WebGPUBuffer.h"
47 #include "WebGPUBufferBinding.h"
48 #include "WebGPUCommandBuffer.h"
49 #include "WebGPUPipelineLayout.h"
50 #include "WebGPUPipelineLayoutDescriptor.h"
51 #include "WebGPUPipelineStageDescriptor.h"
52 #include "WebGPUQueue.h"
53 #include "WebGPURenderPipeline.h"
54 #include "WebGPURenderPipelineDescriptor.h"
55 #include "WebGPUShaderModule.h"
56 #include "WebGPUShaderModuleDescriptor.h"
57 #include "WebGPUTexture.h"
58
59 namespace WebCore {
60
61 RefPtr<WebGPUDevice> WebGPUDevice::create(Ref<WebGPUAdapter>&& adapter)
62 {
63     if (auto device = GPUDevice::create(adapter->options()))
64         return adoptRef(new WebGPUDevice(WTFMove(adapter), device.releaseNonNull()));
65     return nullptr;
66 }
67
68 WebGPUDevice::WebGPUDevice(Ref<WebGPUAdapter>&& adapter, Ref<GPUDevice>&& device)
69     : m_adapter(WTFMove(adapter))
70     , m_device(WTFMove(device))
71 {
72     UNUSED_PARAM(m_adapter);
73 }
74
75 Ref<WebGPUBuffer> WebGPUDevice::createBuffer(GPUBufferDescriptor&& descriptor) const
76 {
77     auto buffer = m_device->tryCreateBuffer(WTFMove(descriptor));
78     return WebGPUBuffer::create(WTFMove(buffer));
79 }
80
81 Ref<WebGPUTexture> WebGPUDevice::createTexture(GPUTextureDescriptor&& descriptor) const
82 {
83     auto texture = m_device->tryCreateTexture(WTFMove(descriptor));
84     return WebGPUTexture::create(WTFMove(texture));
85 }
86
87 Ref<WebGPUBindGroupLayout> WebGPUDevice::createBindGroupLayout(WebGPUBindGroupLayoutDescriptor&& descriptor) const
88 {
89     auto layout = m_device->tryCreateBindGroupLayout(GPUBindGroupLayoutDescriptor { descriptor.bindings });
90     return WebGPUBindGroupLayout::create(WTFMove(layout));
91 }
92
93 Ref<WebGPUPipelineLayout> WebGPUDevice::createPipelineLayout(WebGPUPipelineLayoutDescriptor&& descriptor) const
94 {
95     // FIXME: Is an empty pipelineLayout an error?
96     auto bindGroupLayouts = descriptor.bindGroupLayouts.map([] (const auto& layout) -> RefPtr<const GPUBindGroupLayout> {
97         return layout->bindGroupLayout();
98     });
99     auto layout = m_device->createPipelineLayout(GPUPipelineLayoutDescriptor { WTFMove(bindGroupLayouts) });
100     return WebGPUPipelineLayout::create(WTFMove(layout));
101 }
102
103 Ref<WebGPUBindGroup> WebGPUDevice::createBindGroup(WebGPUBindGroupDescriptor&& descriptor) const
104 {
105     auto gpuDescriptor = descriptor.asGPUBindGroupDescriptor();
106     if (!gpuDescriptor)
107         return WebGPUBindGroup::create(nullptr);
108
109     auto bindGroup = GPUBindGroup::create(WTFMove(*gpuDescriptor));
110     return WebGPUBindGroup::create(WTFMove(bindGroup));
111 }
112
113 RefPtr<WebGPUShaderModule> WebGPUDevice::createShaderModule(WebGPUShaderModuleDescriptor&& descriptor) const
114 {
115     // FIXME: What can be validated here?
116     if (auto module = m_device->createShaderModule(GPUShaderModuleDescriptor { descriptor.code }))
117         return WebGPUShaderModule::create(module.releaseNonNull());
118     return nullptr;
119 }
120
121 static Optional<GPUPipelineStageDescriptor> validateAndConvertPipelineStage(const WebGPUPipelineStageDescriptor& descriptor)
122 {
123     if (!descriptor.module || !descriptor.module->module() || descriptor.entryPoint.isEmpty())
124         return WTF::nullopt;
125
126     return GPUPipelineStageDescriptor { descriptor.module->module(), descriptor.entryPoint };
127 }
128
129 RefPtr<WebGPURenderPipeline> WebGPUDevice::createRenderPipeline(WebGPURenderPipelineDescriptor&& descriptor) const
130 {
131     auto pipelineLayout = descriptor.layout ? descriptor.layout->pipelineLayout() : nullptr;
132
133     auto vertexStage = validateAndConvertPipelineStage(descriptor.vertexStage);
134     auto fragmentStage = validateAndConvertPipelineStage(descriptor.fragmentStage);
135
136     if (!vertexStage || !fragmentStage) {
137         LOG(WebGPU, "WebGPUDevice::createRenderPipeline(): Invalid WebGPUPipelineStageDescriptor!");
138         return nullptr;
139     }
140
141     if (auto pipeline = m_device->createRenderPipeline(GPURenderPipelineDescriptor { WTFMove(pipelineLayout), WTFMove(*vertexStage), WTFMove(*fragmentStage), descriptor.primitiveTopology, WTFMove(descriptor.depthStencilState), WTFMove(descriptor.inputState) }))
142         return WebGPURenderPipeline::create(pipeline.releaseNonNull());
143     return nullptr;
144 }
145
146 RefPtr<WebGPUCommandBuffer> WebGPUDevice::createCommandBuffer() const
147 {
148     if (auto commandBuffer = m_device->createCommandBuffer())
149         return WebGPUCommandBuffer::create(commandBuffer.releaseNonNull());
150     return nullptr;
151 }
152
153 RefPtr<WebGPUQueue> WebGPUDevice::getQueue()
154 {
155     if (!m_queue)
156         m_queue = WebGPUQueue::create(m_device->getQueue());
157
158     return m_queue;
159 }
160
161 } // namespace WebCore
162
163 #endif // ENABLE(WEBGPU)