30591f664e177052d6af700f57464fe67b50cbbd
[WebKit-https.git] / Source / WebCore / Modules / webgpu / WebGPURenderPassEncoder.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 "WebGPURenderPassEncoder.h"
28
29 #if ENABLE(WEBGPU)
30
31 #include "GPUColor.h"
32 #include "GPULimits.h"
33 #include "GPUProgrammablePassEncoder.h"
34 #include "GPURenderPassEncoder.h"
35 #include "Logging.h"
36 #include "WebGPUBuffer.h"
37 #include "WebGPURenderPipeline.h"
38
39 namespace WebCore {
40
41 Ref<WebGPURenderPassEncoder> WebGPURenderPassEncoder::create(RefPtr<GPURenderPassEncoder>&& encoder)
42 {
43     return adoptRef(*new WebGPURenderPassEncoder(WTFMove(encoder)));
44 }
45
46 WebGPURenderPassEncoder::WebGPURenderPassEncoder(RefPtr<GPURenderPassEncoder>&& encoder)
47     : m_passEncoder { WTFMove(encoder) }
48 {
49 }
50
51 void WebGPURenderPassEncoder::setPipeline(const WebGPURenderPipeline& pipeline)
52 {
53     if (!m_passEncoder) {
54         LOG(WebGPU, "GPURenderPassEncoder::setPipeline(): Invalid operation!");
55         return;
56     }
57     if (!pipeline.renderPipeline()) {
58         LOG(WebGPU, "GPURenderPassEncoder::setPipeline(): Invalid pipeline!");
59         return;
60     }
61     m_passEncoder->setPipeline(makeRef(*pipeline.renderPipeline()));
62 }
63
64 void WebGPURenderPassEncoder::setBlendColor(const GPUColor& color)
65 {
66     if (!m_passEncoder) {
67         LOG(WebGPU, "GPURenderPassEncoder::setBlendColor(): Invalid operation!");
68         return;
69     }
70     m_passEncoder->setBlendColor(color);
71 }
72
73 void WebGPURenderPassEncoder::setViewport(float x, float y, float width, float height, float minDepth, float maxDepth)
74 {
75     if (!m_passEncoder) {
76         LOG(WebGPU, "GPURenderPassEncoder::setViewport(): Invalid operation!");
77         return;
78     }
79     m_passEncoder->setViewport(x, y, width, height, minDepth, maxDepth);
80 }
81
82 void WebGPURenderPassEncoder::setScissorRect(unsigned x, unsigned y, unsigned width, unsigned height)
83 {
84     if (!m_passEncoder) {
85         LOG(WebGPU, "GPURenderPassEncoder::setScissorRect(): Invalid operation!");
86         return;
87     }
88     if (!width || !height) {
89         LOG(WebGPU, "GPURenderPassEncoder::setScissorRect(): Width or height must be greater than 0!");
90         return;
91     }
92     m_passEncoder->setScissorRect(x, y, width, height);
93 }
94
95 void WebGPURenderPassEncoder::setVertexBuffers(unsigned startSlot, Vector<RefPtr<WebGPUBuffer>>&& buffers, Vector<uint64_t>&& offsets)
96 {
97 #if !LOG_DISABLED
98     const char* const functionName = "GPURenderPassEncoder::setVertexBuffers()";
99 #endif
100     if (!m_passEncoder) {
101         LOG(WebGPU, "%s: Invalid operation!", functionName);
102         return;
103     }
104     if (buffers.isEmpty() || buffers.size() != offsets.size()) {
105         LOG(WebGPU, "%s: Invalid number of buffers or offsets!", functionName);
106         return;
107     }
108     if (startSlot + buffers.size() > maxVertexBuffers) {
109         LOG(WebGPU, "%s: Invalid startSlot %u for %lu buffers!", functionName, startSlot, buffers.size());
110         return;
111     }
112
113     Vector<Ref<GPUBuffer>> gpuBuffers;
114     gpuBuffers.reserveCapacity(buffers.size());
115
116     for (const auto& buffer : buffers) {
117         if (!buffer || !buffer->buffer()) {
118             LOG(WebGPU, "%s: Invalid or destroyed buffer in list!", functionName);
119             return;
120         }
121
122         if (!buffer->buffer()->isVertex()) {
123             LOG(WebGPU, "%s: Buffer was not created with VERTEX usage!", functionName);
124             return;
125         }
126
127         gpuBuffers.uncheckedAppend(makeRef(*buffer->buffer()));
128     }
129
130     m_passEncoder->setVertexBuffers(startSlot, WTFMove(gpuBuffers), WTFMove(offsets));
131 }
132
133 void WebGPURenderPassEncoder::draw(unsigned vertexCount, unsigned instanceCount, unsigned firstVertex, unsigned firstInstance)
134 {
135     if (!m_passEncoder) {
136         LOG(WebGPU, "GPURenderPassEncoder::draw(): Invalid operation!");
137         return;
138     }
139     // FIXME: What kind of validation do we need to handle here?
140     m_passEncoder->draw(vertexCount, instanceCount, firstVertex, firstInstance);
141 }
142
143 GPUProgrammablePassEncoder* WebGPURenderPassEncoder::passEncoder()
144 {
145     return m_passEncoder.get();
146 }
147
148 const GPUProgrammablePassEncoder* WebGPURenderPassEncoder::passEncoder() const
149 {
150     return m_passEncoder.get();
151 }
152
153 } // namespace WebCore
154
155 #endif // ENABLE(WEBGPU)