Add preliminary OpenGL ES and EGL support to Dawn.
This is enough to get all of the sample apps running on a conformant ES 3.1 implementation, such as ANGLE/Vk or NVidia's OpenGL ES Linux driver. Implements a new opengl::AdapterDiscoveryOptionsES subclass to specify its creation at adapter discovery time. Adds a "-b opengles" command-line flag to the code samples. Asserts on a call to glShaderStorageBlockBinding() on ES. Works around missing indexed draw buffers support by asserting when a non-0 color attachment is specified. Works around missing glClearTexSubImage() by asserting. :/ These will likely require front-end validation. BUG=dawn:580 Change-Id: I4a4240ca695a22388c55073fd2aee0323cd4afc9 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/31000 Reviewed-by: Stephen White <senorblanco@chromium.org> Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
parent
90bac683b4
commit
70102b7190
|
@ -213,12 +213,17 @@ bool InitSample(int argc, const char** argv) {
|
|||
backendType = wgpu::BackendType::OpenGL;
|
||||
continue;
|
||||
}
|
||||
if (i < argc && std::string("opengles") == argv[i]) {
|
||||
backendType = wgpu::BackendType::OpenGLES;
|
||||
continue;
|
||||
}
|
||||
if (i < argc && std::string("vulkan") == argv[i]) {
|
||||
backendType = wgpu::BackendType::Vulkan;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n");
|
||||
"--backend expects a backend name (opengl, opengles, metal, d3d12, null, "
|
||||
"vulkan)\n");
|
||||
return false;
|
||||
}
|
||||
if (std::string("-c") == argv[i] || std::string("--command-buffer") == argv[i]) {
|
||||
|
|
|
@ -69,9 +69,10 @@ namespace dawn_native {
|
|||
return BackendType::OpenGL;
|
||||
case wgpu::BackendType::Vulkan:
|
||||
return BackendType::Vulkan;
|
||||
case wgpu::BackendType::OpenGLES:
|
||||
return BackendType::OpenGLES;
|
||||
|
||||
case wgpu::BackendType::D3D11:
|
||||
case wgpu::BackendType::OpenGLES:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace dawn_native {
|
|||
#endif // defined(DAWN_ENABLE_BACKEND_NULL)
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
namespace opengl {
|
||||
BackendConnection* Connect(InstanceBase* instance);
|
||||
BackendConnection* Connect(InstanceBase* instance, wgpu::BackendType backendType);
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||
|
@ -147,7 +147,8 @@ namespace dawn_native {
|
|||
# endif // defined(DAWN_ENABLE_SWIFTSHADER)
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
Register(opengl::Connect(this), wgpu::BackendType::OpenGL);
|
||||
Register(opengl::Connect(this, wgpu::BackendType::OpenGL), wgpu::BackendType::OpenGL);
|
||||
Register(opengl::Connect(this, wgpu::BackendType::OpenGLES), wgpu::BackendType::OpenGLES);
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
#if defined(DAWN_ENABLE_BACKEND_NULL)
|
||||
Register(null::Connect(this), wgpu::BackendType::Null);
|
||||
|
|
|
@ -119,12 +119,18 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
class Adapter : public AdapterBase {
|
||||
public:
|
||||
Adapter(InstanceBase* instance) : AdapterBase(instance, wgpu::BackendType::OpenGL) {
|
||||
Adapter(InstanceBase* instance, wgpu::BackendType backendType)
|
||||
: AdapterBase(instance, backendType) {
|
||||
}
|
||||
|
||||
MaybeError Initialize(const AdapterDiscoveryOptions* options) {
|
||||
// Use getProc to populate the dispatch table
|
||||
DAWN_TRY(mFunctions.Initialize(options->getProc));
|
||||
if (mFunctions.GetVersion().IsES()) {
|
||||
ASSERT(GetBackendType() == wgpu::BackendType::OpenGLES);
|
||||
} else {
|
||||
ASSERT(GetBackendType() == wgpu::BackendType::OpenGL);
|
||||
}
|
||||
|
||||
// Use the debug output functionality to get notified about GL errors
|
||||
// TODO(cwallez@chromium.org): add support for the KHR_debug and ARB_debug_output
|
||||
|
@ -160,7 +166,9 @@ namespace dawn_native { namespace opengl {
|
|||
mFunctions.Enable(GL_DEPTH_TEST);
|
||||
mFunctions.Enable(GL_SCISSOR_TEST);
|
||||
mFunctions.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
|
||||
mFunctions.Enable(GL_MULTISAMPLE);
|
||||
if (mFunctions.GetVersion().IsDesktop()) {
|
||||
mFunctions.Enable(GL_MULTISAMPLE);
|
||||
}
|
||||
mFunctions.Enable(GL_FRAMEBUFFER_SRGB);
|
||||
mFunctions.Enable(GL_SAMPLE_MASK);
|
||||
|
||||
|
@ -229,8 +237,8 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
// Implementation of the OpenGL backend's BackendConnection
|
||||
|
||||
Backend::Backend(InstanceBase* instance)
|
||||
: BackendConnection(instance, wgpu::BackendType::OpenGL) {
|
||||
Backend::Backend(InstanceBase* instance, wgpu::BackendType backendType)
|
||||
: BackendConnection(instance, backendType) {
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
|
||||
|
@ -246,7 +254,7 @@ namespace dawn_native { namespace opengl {
|
|||
return DAWN_VALIDATION_ERROR("The OpenGL backend can only create a single adapter");
|
||||
}
|
||||
|
||||
ASSERT(optionsBase->backendType == WGPUBackendType_OpenGL);
|
||||
ASSERT(static_cast<wgpu::BackendType>(optionsBase->backendType) == GetType());
|
||||
const AdapterDiscoveryOptions* options =
|
||||
static_cast<const AdapterDiscoveryOptions*>(optionsBase);
|
||||
|
||||
|
@ -254,7 +262,8 @@ namespace dawn_native { namespace opengl {
|
|||
return DAWN_VALIDATION_ERROR("AdapterDiscoveryOptions::getProc must be set");
|
||||
}
|
||||
|
||||
std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(GetInstance());
|
||||
std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(
|
||||
GetInstance(), static_cast<wgpu::BackendType>(optionsBase->backendType));
|
||||
DAWN_TRY(adapter->Initialize(options));
|
||||
|
||||
mCreatedAdapter = true;
|
||||
|
@ -263,8 +272,8 @@ namespace dawn_native { namespace opengl {
|
|||
return std::move(adapters);
|
||||
}
|
||||
|
||||
BackendConnection* Connect(InstanceBase* instance) {
|
||||
return new Backend(instance);
|
||||
BackendConnection* Connect(InstanceBase* instance, wgpu::BackendType backendType) {
|
||||
return new Backend(instance, backendType);
|
||||
}
|
||||
|
||||
}} // namespace dawn_native::opengl
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
class Backend : public BackendConnection {
|
||||
public:
|
||||
Backend(InstanceBase* instance);
|
||||
Backend(InstanceBase* instance, wgpu::BackendType backendType);
|
||||
|
||||
std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
|
||||
ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace dawn_native { namespace opengl {
|
|||
MaybeError Buffer::MapAtCreationImpl() {
|
||||
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
|
||||
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
mMappedData = gl.MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
mMappedData = gl.MapBufferRange(GL_ARRAY_BUFFER, 0, GetSize(), GL_MAP_WRITE_BIT);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -944,7 +944,7 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
// Load op - color
|
||||
if (attachmentInfo->loadOp == wgpu::LoadOp::Clear) {
|
||||
gl.ColorMaski(i, true, true, true, true);
|
||||
gl.ColorMask(true, true, true, true);
|
||||
|
||||
wgpu::TextureComponentType baseType =
|
||||
attachmentInfo->view->GetFormat().GetAspectInfo(Aspect::Color).baseType;
|
||||
|
|
|
@ -27,6 +27,10 @@ namespace dawn_native { namespace opengl {
|
|||
: AdapterDiscoveryOptionsBase(WGPUBackendType_OpenGL) {
|
||||
}
|
||||
|
||||
AdapterDiscoveryOptionsES::AdapterDiscoveryOptionsES()
|
||||
: AdapterDiscoveryOptionsBase(WGPUBackendType_OpenGLES) {
|
||||
}
|
||||
|
||||
DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device,
|
||||
PresentCallback present,
|
||||
void* presentUserdata) {
|
||||
|
|
|
@ -134,8 +134,14 @@ namespace dawn_native { namespace opengl {
|
|||
GLuint location = gl.GetProgramResourceIndex(
|
||||
mProgram, GL_SHADER_STORAGE_BLOCK, name.c_str());
|
||||
if (location != GL_INVALID_INDEX) {
|
||||
gl.ShaderStorageBlockBinding(mProgram, location,
|
||||
indices[group][bindingIndex]);
|
||||
if (gl.GetVersion().IsES()) {
|
||||
// TODO(crbug.com/dawn/584): Figure out a substitute for
|
||||
// glShaderStorageBlockBinding on ES or add additional validation.
|
||||
ASSERT(false);
|
||||
} else {
|
||||
gl.ShaderStorageBlockBinding(mProgram, location,
|
||||
indices[group][bindingIndex]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -106,23 +106,44 @@ namespace dawn_native { namespace opengl {
|
|||
ColorAttachmentIndex attachment,
|
||||
const ColorStateDescriptor* descriptor) {
|
||||
GLuint colorBuffer = static_cast<GLuint>(static_cast<uint8_t>(attachment));
|
||||
if (BlendEnabled(descriptor)) {
|
||||
gl.Enablei(GL_BLEND, colorBuffer);
|
||||
gl.BlendEquationSeparatei(colorBuffer,
|
||||
GLBlendMode(descriptor->colorBlend.operation),
|
||||
GLBlendMode(descriptor->alphaBlend.operation));
|
||||
gl.BlendFuncSeparatei(colorBuffer,
|
||||
GLBlendFactor(descriptor->colorBlend.srcFactor, false),
|
||||
GLBlendFactor(descriptor->colorBlend.dstFactor, false),
|
||||
GLBlendFactor(descriptor->alphaBlend.srcFactor, true),
|
||||
GLBlendFactor(descriptor->alphaBlend.dstFactor, true));
|
||||
if (gl.IsAtLeastGL(3, 0) || gl.IsAtLeastGLES(3, 2)) {
|
||||
if (BlendEnabled(descriptor)) {
|
||||
gl.Enablei(GL_BLEND, colorBuffer);
|
||||
gl.BlendEquationSeparatei(colorBuffer,
|
||||
GLBlendMode(descriptor->colorBlend.operation),
|
||||
GLBlendMode(descriptor->alphaBlend.operation));
|
||||
gl.BlendFuncSeparatei(colorBuffer,
|
||||
GLBlendFactor(descriptor->colorBlend.srcFactor, false),
|
||||
GLBlendFactor(descriptor->colorBlend.dstFactor, false),
|
||||
GLBlendFactor(descriptor->alphaBlend.srcFactor, true),
|
||||
GLBlendFactor(descriptor->alphaBlend.dstFactor, true));
|
||||
} else {
|
||||
gl.Disablei(GL_BLEND, colorBuffer);
|
||||
}
|
||||
gl.ColorMaski(colorBuffer, descriptor->writeMask & wgpu::ColorWriteMask::Red,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Green,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Blue,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Alpha);
|
||||
} else {
|
||||
gl.Disablei(GL_BLEND, colorBuffer);
|
||||
// TODO(crbug.com/dawn/582): Add validation to prevent this as it is not supported
|
||||
// on GLES < 3.2.
|
||||
DAWN_ASSERT(colorBuffer == 0);
|
||||
if (BlendEnabled(descriptor)) {
|
||||
gl.Enable(GL_BLEND);
|
||||
gl.BlendEquationSeparate(GLBlendMode(descriptor->colorBlend.operation),
|
||||
GLBlendMode(descriptor->alphaBlend.operation));
|
||||
gl.BlendFuncSeparate(GLBlendFactor(descriptor->colorBlend.srcFactor, false),
|
||||
GLBlendFactor(descriptor->colorBlend.dstFactor, false),
|
||||
GLBlendFactor(descriptor->alphaBlend.srcFactor, true),
|
||||
GLBlendFactor(descriptor->alphaBlend.dstFactor, true));
|
||||
} else {
|
||||
gl.Disable(GL_BLEND);
|
||||
}
|
||||
gl.ColorMask(descriptor->writeMask & wgpu::ColorWriteMask::Red,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Green,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Blue,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Alpha);
|
||||
}
|
||||
gl.ColorMaski(colorBuffer, descriptor->writeMask & wgpu::ColorWriteMask::Red,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Green,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Blue,
|
||||
descriptor->writeMask & wgpu::ColorWriteMask::Alpha);
|
||||
}
|
||||
|
||||
GLuint OpenGLStencilOperation(wgpu::StencilOperation stencilOperation) {
|
||||
|
|
|
@ -323,10 +323,16 @@ namespace dawn_native { namespace opengl {
|
|||
// Skip lazy clears if already initialized.
|
||||
continue;
|
||||
}
|
||||
gl.ClearTexSubImage(mHandle, static_cast<GLint>(level), 0, 0,
|
||||
static_cast<GLint>(layer), mipSize.width,
|
||||
mipSize.height, 1, glFormat.format, glFormat.type,
|
||||
clearColorData.data());
|
||||
if (gl.IsAtLeastGL(4, 4)) {
|
||||
gl.ClearTexSubImage(mHandle, static_cast<GLint>(level), 0, 0,
|
||||
static_cast<GLint>(layer), mipSize.width,
|
||||
mipSize.height, 1, glFormat.format, glFormat.type,
|
||||
clearColorData.data());
|
||||
} else {
|
||||
// TODO(crbug.com/dawn/581): Implement a fallback path on OpenGL ES
|
||||
// because it doesn't support glClearTexSubImage.
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace dawn_native {
|
|||
Metal,
|
||||
Null,
|
||||
OpenGL,
|
||||
OpenGLES,
|
||||
Vulkan,
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,12 @@ namespace dawn_native { namespace opengl {
|
|||
void* (*getProc)(const char*);
|
||||
};
|
||||
|
||||
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptionsES : public AdapterDiscoveryOptionsBase {
|
||||
AdapterDiscoveryOptionsES();
|
||||
|
||||
void* (*getProc)(const char*);
|
||||
};
|
||||
|
||||
using PresentCallback = void (*)(void*);
|
||||
DAWN_NATIVE_EXPORT DawnSwapChainImplementation
|
||||
CreateNativeSwapChainImpl(WGPUDevice device, PresentCallback present, void* presentUserdata);
|
||||
|
|
|
@ -50,12 +50,19 @@ namespace utils {
|
|||
DAWN_UNUSED(type);
|
||||
DAWN_UNUSED(window);
|
||||
|
||||
if (type == wgpu::BackendType::OpenGL) {
|
||||
if (type == wgpu::BackendType::OpenGL || type == wgpu::BackendType::OpenGLES) {
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
glfwMakeContextCurrent(window);
|
||||
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
|
||||
adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
|
||||
instance->DiscoverAdapters(&adapterOptions);
|
||||
auto getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
|
||||
if (type == wgpu::BackendType::OpenGL) {
|
||||
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
|
||||
adapterOptions.getProc = getProc;
|
||||
instance->DiscoverAdapters(&adapterOptions);
|
||||
} else {
|
||||
dawn_native::opengl::AdapterDiscoveryOptionsES adapterOptions;
|
||||
adapterOptions.getProc = getProc;
|
||||
instance->DiscoverAdapters(&adapterOptions);
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
} else {
|
||||
instance->DiscoverDefaultAdapters();
|
||||
|
@ -81,6 +88,7 @@ namespace utils {
|
|||
|
||||
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||
case wgpu::BackendType::OpenGL:
|
||||
case wgpu::BackendType::OpenGLES:
|
||||
return CreateOpenGLBinding(window, device);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace utils {
|
|||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
} else if (type == wgpu::BackendType::OpenGLES) {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
|
||||
} else {
|
||||
// Without this GLFW will initialize a GL context on the window, which prevents using
|
||||
// the window with other APIs (by crashing in weird ways).
|
||||
|
|
Loading…
Reference in New Issue