haikuwebkit/Source/WebCore/html/canvas/WebGLMultiDraw.cpp

149 lines
6.8 KiB
C++
Raw Permalink Normal View History

Support WEBGL_multi_draw extension https://bugs.webkit.org/show_bug.cgi?id=219139 Patch by Kenneth Russell <kbr@chromium.org> on 2021-01-20 Reviewed by Dean Jackson. Source/WebCore: Support the WEBGL_multi_draw extension in WebKit, delegating to ANGLE's underlying implementation. This extension significantly reduces draw-call overhead in certain scenarios, and is requested by CAD/CAM web apps using WebGL. Test: webgl/conformance/extensions/webgl-multi-draw.html * CMakeLists.txt: * DerivedSources-input.xcfilelist: * DerivedSources-output.xcfilelist: * DerivedSources.make: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: * bindings/js/JSDOMConvertWebGL.cpp: (WebCore::convertToJSValue): * html/canvas/WebGL2RenderingContext.cpp: (WebCore::WebGL2RenderingContext::getExtension): (WebCore::WebGL2RenderingContext::getSupportedExtensions): * html/canvas/WebGLExtension.h: * html/canvas/WebGLMultiDraw.cpp: Added. (WebCore::makeSpanWithOffset): (WebCore::WebGLMultiDraw::WebGLMultiDraw): (WebCore::WebGLMultiDraw::getName const): (WebCore::WebGLMultiDraw::supported): (WebCore::WebGLMultiDraw::multiDrawArraysWEBGL): (WebCore::WebGLMultiDraw::multiDrawArraysInstancedWEBGL): (WebCore::WebGLMultiDraw::multiDrawElementsWEBGL): (WebCore::WebGLMultiDraw::multiDrawElementsInstancedWEBGL): (WebCore::WebGLMultiDraw::validateDrawcount): (WebCore::WebGLMultiDraw::validateOffset): * html/canvas/WebGLMultiDraw.h: Added. * html/canvas/WebGLMultiDraw.idl: Added. * html/canvas/WebGLRenderingContext.cpp: (WebCore::WebGLRenderingContext::getExtension): (WebCore::WebGLRenderingContext::getSupportedExtensions): * html/canvas/WebGLRenderingContextBase.cpp: (WebCore::WebGLRenderingContextBase::extensionIsEnabled): * html/canvas/WebGLRenderingContextBase.h: * platform/graphics/GraphicsContextGL.h: * platform/graphics/angle/GraphicsContextGLANGLE.cpp: (WebCore::GraphicsContextGLOpenGL::multiDrawArraysANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawArraysInstancedANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawElementsANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawElementsInstancedANGLE): * platform/graphics/opengl/GraphicsContextGLOpenGL.h: * platform/graphics/opengl/GraphicsContextGLOpenGLCommon.cpp: (WebCore::GraphicsContextGLOpenGL::multiDrawArraysANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawArraysInstancedANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawElementsANGLE): (WebCore::GraphicsContextGLOpenGL::multiDrawElementsInstancedANGLE): Source/WebInspectorUI: Tell the Inspector about the method signatures in the WEBGL_multi_draw extension. * UserInterface/Models/NativeFunctionParameters.js: Source/WebKit: Add automatically-generated stubs for supporting the multi-draw extension in the GPU process. * GPUProcess/graphics/RemoteGraphicsContextGL.messages.in: * GPUProcess/graphics/RemoteGraphicsContextGLFunctionsGenerated.h: (multiDrawArraysANGLE): (multiDrawArraysInstancedANGLE): (multiDrawElementsANGLE): (multiDrawElementsInstancedANGLE): * WebProcess/GPU/graphics/RemoteGraphicsContextGLProxy.h: * WebProcess/GPU/graphics/RemoteGraphicsContextGLProxyFunctionsGenerated.cpp: (WebKit::RemoteGraphicsContextGLProxy::multiDrawArraysANGLE): (WebKit::RemoteGraphicsContextGLProxy::multiDrawArraysInstancedANGLE): (WebKit::RemoteGraphicsContextGLProxy::multiDrawElementsANGLE): (WebKit::RemoteGraphicsContextGLProxy::multiDrawElementsInstancedANGLE): LayoutTests: Add conformance test for the multi-draw extension, which is expected to pass. Temporarily suppress the test due to failures on Intel GPUs on macOS caused by recently-discovered OpenGL driver bugs, which are currently being investigated. * TestExpectations: * webgl/conformance/extensions/webgl-multi-draw-expected.txt: Added. * webgl/conformance/extensions/webgl-multi-draw.html: Added. * webgl/resources/webgl_test_files/conformance/extensions/webgl-multi-draw.html: Added. Canonical link: https://commits.webkit.org/233192@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271679 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-01-21 01:42:45 +00:00
/*
* Copyright (C) 2021 Google 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 AND ITS CONTRIBUTORS "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 OR ITS 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.
*/
#include "config.h"
#if ENABLE(WEBGL)
#include "WebGLMultiDraw.h"
#include "ExtensionsGL.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(WebGLMultiDraw);
static GCGLSpan<const int> makeSpanWithOffset(WebGLMultiDraw::Int32List& list, GCGLuint offset)
{
return makeGCGLSpan(list.data() + offset, list.length() - offset);
}
WebGLMultiDraw::WebGLMultiDraw(WebGLRenderingContextBase& context)
: WebGLExtension(context)
{
context.graphicsContextGL()->getExtensions().ensureEnabled("GL_ANGLE_multi_draw"_s);
context.graphicsContextGL()->getExtensions().ensureEnabled("GL_ANGLE_instanced_arrays"_s);
}
WebGLMultiDraw::~WebGLMultiDraw() = default;
WebGLExtension::ExtensionName WebGLMultiDraw::getName() const
{
return WebGLMultiDrawName;
}
bool WebGLMultiDraw::supported(const WebGLRenderingContextBase& context)
{
return context.graphicsContextGL()->getExtensions().supports("GL_ANGLE_multi_draw"_s)
&& context.graphicsContextGL()->getExtensions().supports("GL_ANGLE_instanced_arrays"_s);
}
void WebGLMultiDraw::multiDrawArraysWEBGL(GCGLenum mode, Int32List firstsList, GCGLuint firstsOffset, Int32List countsList, GCGLuint countsOffset, GCGLsizei drawcount)
{
if (!m_context || m_context->isContextLost())
return;
if (!validateDrawcount("multiDrawArraysWEBGL", drawcount)
|| !validateOffset("multiDrawArraysWEBGL", "firstsOffset out of bounds", firstsList.length(), firstsOffset, drawcount)
|| !validateOffset("multiDrawArraysWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)) {
return;
}
m_context->graphicsContextGL()->multiDrawArraysANGLE(mode, makeSpanWithOffset(firstsList, firstsOffset), makeSpanWithOffset(countsList, countsOffset), drawcount);
}
void WebGLMultiDraw::multiDrawArraysInstancedWEBGL(GCGLenum mode, Int32List firstsList, GCGLuint firstsOffset, Int32List countsList, GCGLuint countsOffset, Int32List instanceCountsList, GCGLuint instanceCountsOffset, GCGLsizei drawcount)
{
if (!m_context || m_context->isContextLost())
return;
if (!validateDrawcount("multiDrawArraysInstancedWEBGL", drawcount)
|| !validateOffset("multiDrawArraysInstancedWEBGL", "firstsOffset out of bounds", firstsList.length(), firstsOffset, drawcount)
|| !validateOffset("multiDrawArraysInstancedWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)
|| !validateOffset("multiDrawArraysInstancedWEBGL", "instanceCountsOffset out of bounds", instanceCountsList.length(), instanceCountsOffset, drawcount)) {
return;
}
m_context->graphicsContextGL()->multiDrawArraysInstancedANGLE(mode, makeSpanWithOffset(firstsList, firstsOffset), makeSpanWithOffset(countsList, countsOffset), makeSpanWithOffset(instanceCountsList, instanceCountsOffset), drawcount);
}
void WebGLMultiDraw::multiDrawElementsWEBGL(GCGLenum mode, Int32List countsList, GCGLuint countsOffset, GCGLenum type, Int32List offsetsList, GCGLuint offsetsOffset, GCGLsizei drawcount)
{
if (!m_context || m_context->isContextLost())
return;
if (!validateDrawcount("multiDrawElementsWEBGL", drawcount)
|| !validateOffset("multiDrawElementsWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)
|| !validateOffset("multiDrawElementsWEBGL", "offsetsOffset out of bounds", offsetsList.length(), offsetsOffset, drawcount)) {
return;
}
m_context->graphicsContextGL()->multiDrawElementsANGLE(mode, makeSpanWithOffset(countsList, countsOffset), type, makeSpanWithOffset(offsetsList, offsetsOffset), drawcount);
}
void WebGLMultiDraw::multiDrawElementsInstancedWEBGL(GCGLenum mode, Int32List countsList, GCGLuint countsOffset, GCGLenum type, Int32List offsetsList, GCGLuint offsetsOffset, Int32List instanceCountsList, GCGLuint instanceCountsOffset, GCGLsizei drawcount)
{
if (!m_context || m_context->isContextLost())
return;
if (!validateDrawcount("multiDrawElementsWEBGL", drawcount)
|| !validateOffset("multiDrawElementsWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)
|| !validateOffset("multiDrawElementsWEBGL", "offsetsOffset out of bounds", offsetsList.length(), offsetsOffset, drawcount)
|| !validateOffset("multiDrawElementsWEBGL", "countsOffset out of bounds", instanceCountsList.length(), instanceCountsOffset, drawcount)) {
return;
}
m_context->graphicsContextGL()->multiDrawElementsInstancedANGLE(mode, makeSpanWithOffset(countsList, countsOffset), type, makeSpanWithOffset(offsetsList, offsetsOffset), makeSpanWithOffset(instanceCountsList, instanceCountsOffset), drawcount);
}
bool WebGLMultiDraw::validateDrawcount(const char* functionName, GCGLsizei drawcount)
{
if (drawcount < 0) {
m_context->synthesizeGLError(GraphicsContextGL::INVALID_VALUE, functionName, "negative drawcount");
return false;
}
return true;
}
bool WebGLMultiDraw::validateOffset(const char* functionName, const char* outOfBoundsDescription, GCGLsizei size, GCGLuint offset, GCGLsizei drawcount)
{
if (drawcount > size) {
m_context->synthesizeGLError(GraphicsContextGL::INVALID_OPERATION, functionName, "drawcount out of bounds");
return false;
}
if (offset >= static_cast<GCGLuint>(size)) {
m_context->synthesizeGLError(GraphicsContextGL::INVALID_OPERATION, functionName, outOfBoundsDescription);
return false;
}
return true;
}
} // namespace WebCore
#endif // ENABLE(WEBGL)