blob: f309c61c8e8bb9ffc448ea01b53173fb21f04127 [file] [log] [blame]
// Copyright 2022 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn/native/opengl/AdapterGL.h"
#include <memory>
#include <string>
#include <utility>
#include "dawn/common/GPUInfo.h"
#include "dawn/native/Instance.h"
#include "dawn/native/opengl/ContextEGL.h"
#include "dawn/native/opengl/DeviceGL.h"
namespace dawn::native::opengl {
namespace {
struct Vendor {
const char* vendorName;
uint32_t vendorId;
};
const Vendor kVendors[] = {{"ATI", gpu_info::kVendorID_AMD},
{"ARM", gpu_info::kVendorID_ARM},
{"Imagination", gpu_info::kVendorID_ImgTec},
{"Intel", gpu_info::kVendorID_Intel},
{"NVIDIA", gpu_info::kVendorID_Nvidia},
{"Qualcomm", gpu_info::kVendorID_Qualcomm}};
uint32_t GetVendorIdFromVendors(const char* vendor) {
uint32_t vendorId = 0;
for (const auto& it : kVendors) {
// Matching vendor name with vendor string
if (strstr(vendor, it.vendorName) != nullptr) {
vendorId = it.vendorId;
break;
}
}
return vendorId;
}
} // anonymous namespace
Adapter::Adapter(InstanceBase* instance, wgpu::BackendType backendType)
: AdapterBase(instance, backendType) {}
MaybeError Adapter::InitializeGLFunctions(void* (*getProc)(const char*)) {
// Use getProc to populate the dispatch table
mEGLFunctions.Init(getProc);
return mFunctions.Initialize(getProc);
}
bool Adapter::SupportsExternalImages() const {
// Via dawn::native::opengl::WrapExternalEGLImage
return GetBackendType() == wgpu::BackendType::OpenGLES;
}
MaybeError Adapter::InitializeImpl() {
if (mFunctions.GetVersion().IsES()) {
ASSERT(GetBackendType() == wgpu::BackendType::OpenGLES);
} else {
ASSERT(GetBackendType() == wgpu::BackendType::OpenGL);
}
mName = reinterpret_cast<const char*>(mFunctions.GetString(GL_RENDERER));
// Workaroud to find vendor id from vendor name
const char* vendor = reinterpret_cast<const char*>(mFunctions.GetString(GL_VENDOR));
mVendorId = GetVendorIdFromVendors(vendor);
mDriverDescription = std::string("OpenGL version ") +
reinterpret_cast<const char*>(mFunctions.GetString(GL_VERSION));
if (mName.find("SwiftShader") != std::string::npos) {
mAdapterType = wgpu::AdapterType::CPU;
}
return {};
}
MaybeError Adapter::InitializeSupportedFeaturesImpl() {
// TextureCompressionBC
{
// BC1, BC2 and BC3 are not supported in OpenGL or OpenGL ES core features.
bool supportsS3TC =
mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc") ||
(mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_dxt1") &&
mFunctions.IsGLExtensionSupported("GL_ANGLE_texture_compression_dxt3") &&
mFunctions.IsGLExtensionSupported("GL_ANGLE_texture_compression_dxt5"));
// COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT and
// COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT requires both GL_EXT_texture_sRGB and
// GL_EXT_texture_compression_s3tc on desktop OpenGL drivers.
// (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_sRGB.txt)
bool supportsTextureSRGB = mFunctions.IsGLExtensionSupported("GL_EXT_texture_sRGB");
// GL_EXT_texture_compression_s3tc_srgb is an extension in OpenGL ES.
// NVidia GLES drivers don't support this extension, but they do support
// GL_NV_sRGB_formats. (Note that GL_EXT_texture_sRGB does not exist on ES.
// GL_EXT_sRGB does (core in ES 3.0), but it does not automatically provide S3TC
// SRGB support even if S3TC is supported; see
// https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_sRGB.txt.)
bool supportsS3TCSRGB =
mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc_srgb") ||
mFunctions.IsGLExtensionSupported("GL_NV_sRGB_formats");
// BC4 and BC5
bool supportsRGTC = mFunctions.IsAtLeastGL(3, 0) ||
mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_rgtc") ||
mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_rgtc");
// BC6 and BC7
bool supportsBPTC = mFunctions.IsAtLeastGL(4, 2) ||
mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_bptc") ||
mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_bptc");
if (supportsS3TC && (supportsTextureSRGB || supportsS3TCSRGB) && supportsRGTC &&
supportsBPTC) {
mSupportedFeatures.EnableFeature(dawn::native::Feature::TextureCompressionBC);
}
}
// Non-zero baseInstance requires at least desktop OpenGL 4.2, and it is not supported in
// OpenGL ES OpenGL:
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsIndirect.xhtml
// OpenGL ES:
// https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glDrawElementsIndirect.xhtml
if (mFunctions.IsAtLeastGL(4, 2)) {
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
}
// ShaderF16
if (mFunctions.IsGLExtensionSupported("GL_AMD_gpu_shader_half_float")) {
mSupportedFeatures.EnableFeature(Feature::ShaderF16);
}
return {};
}
MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
GetDefaultLimits(&limits->v1);
return {};
}
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(
const DeviceDescriptor* descriptor,
const TripleStateTogglesSet& userProvidedToggles) {
EGLenum api =
GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
std::unique_ptr<Device::Context> context;
DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api));
return Device::Create(this, descriptor, mFunctions, std::move(context), userProvidedToggles);
}
MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(
wgpu::FeatureName feature,
const TripleStateTogglesSet& userProvidedToggles) {
return {};
}
} // namespace dawn::native::opengl