gpu-dawn: remove Mach C shims

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2022-07-30 16:25:47 -07:00
parent 70ee58c904
commit 0e68ba36eb
5 changed files with 4 additions and 415 deletions

View file

@ -66,11 +66,6 @@ You should be aware:
* The `webgpu.h` API is still changing
* Dawn and gfx-rs/wgpu, although both try to implement `webgpu.h`, do not exactly implement the same interface. There are subtle differences in device discovery & creation for example.
Some of Dawn's API is not available as a C API today. For example, OpenGL device discovery. You may find the following C shims we build for Mach engine useful for interfacing with Dawn from other languages (copy these into your own project, they are not built into the static dawn library):
* [dawn_native_mach.h](https://github.com/hexops/mach/blob/main/gpu-dawn/src/dawn/dawn_native_mach.h)
* [dawn_native-mach.cpp](https://github.com/hexops/mach/blob/main/gpu-dawn/src/dawn/dawn_native_mach.cpp)
## Generated code
Dawn itself relies on a fairly large amount of dependencies, generated code, etc. To avoid having any dependency on Google build tools, code generation, etc. we maintain [a minor fork of Dawn which has generated code and third-party dependencies comitted in "generated" branches.](https://github.com/hexops/dawn/tree/main/mach) We are usually up-to-date with the upstream within a few weeks on average.

View file

@ -504,10 +504,6 @@ fn buildLibMachDawnNative(b: *Builder, step: *std.build.LibExeObjStep, options:
"-D_DLL",
}) catch unreachable;
}
lib.addCSourceFile(std.fs.path.join(b.allocator, &.{
(comptime thisDir()), "src/dawn/dawn_native_mach.cpp",
}) catch unreachable, cpp_flags.items);
return lib;
}
@ -530,7 +526,10 @@ fn buildLibDawnCommon(b: *Builder, step: *std.build.LibExeObjStep, options: Opti
include("libs/dawn/out/Debug/gen/src"),
}) catch unreachable;
appendLangScannedSources(b, lib, options, .{
.rel_dirs = &.{"libs/dawn/src/dawn/common/"},
.rel_dirs = &.{
"libs/dawn/src/dawn/common/",
"libs/dawn/out/Debug/gen/src/dawn/common/",
},
.flags = flags.items,
.excluding_contains = &.{
"test",

View file

@ -1,5 +1,4 @@
pub const c = @cImport({
@cInclude("dawn/webgpu.h");
@cInclude("dawn/dawn_proc.h");
@cInclude("dawn_native_mach.h");
});

View file

@ -1,284 +0,0 @@
#include <dawn/native/DawnNative.h>
#include <dawn/native/wgpu_structs_autogen.h>
#include "dawn/utils/BackendBinding.h"
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
#include <dawn/native/OpenGLBackend.h>
#endif
#include "dawn_native_mach.h"
#ifdef __cplusplus
extern "C" {
#endif
// wgpu::AdapterProperties wrappers
MACH_EXPORT void machDawnNativeAdapterProperties_deinit(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
delete self;
}
MACH_EXPORT uint32_t machDawnNativeAdapterProperties_getVendorID(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
return self->vendorID;
}
MACH_EXPORT uint32_t machDawnNativeAdapterProperties_getDeviceID(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
return self->deviceID;
}
MACH_EXPORT char const* machDawnNativeAdapterProperties_getName(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
return self->name;
}
MACH_EXPORT char const* machDawnNativeAdapterProperties_getDriverDescription(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
return self->driverDescription;
}
MACH_EXPORT WGPUAdapterType machDawnNativeAdapterProperties_getAdapterType(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
switch (self->adapterType) {
case wgpu::AdapterType::DiscreteGPU: return WGPUAdapterType_DiscreteGPU;
case wgpu::AdapterType::IntegratedGPU: return WGPUAdapterType_IntegratedGPU;
case wgpu::AdapterType::CPU: return WGPUAdapterType_CPU;
case wgpu::AdapterType::Unknown: return WGPUAdapterType_Unknown;
}
}
MACH_EXPORT WGPUBackendType machDawnNativeAdapterProperties_getBackendType(MachDawnNativeAdapterProperties properties) {
auto self = reinterpret_cast<wgpu::AdapterProperties*>(properties);
switch (self->backendType) {
case wgpu::BackendType::WebGPU: return WGPUBackendType_WebGPU;
case wgpu::BackendType::D3D11: return WGPUBackendType_D3D11;
case wgpu::BackendType::D3D12: return WGPUBackendType_D3D12;
case wgpu::BackendType::Metal: return WGPUBackendType_Metal;
case wgpu::BackendType::Null: return WGPUBackendType_Null;
case wgpu::BackendType::OpenGL: return WGPUBackendType_OpenGL;
case wgpu::BackendType::OpenGLES: return WGPUBackendType_OpenGLES;
case wgpu::BackendType::Vulkan: return WGPUBackendType_Vulkan;
}
}
// dawn_native::Adapter wrappers
MACH_EXPORT MachDawnNativeAdapterProperties machDawnNativeAdapter_getProperties(MachDawnNativeAdapter adapter) {
auto self = reinterpret_cast<dawn_native::Adapter*>(adapter);
auto cppProperties = new wgpu::AdapterProperties();
self->GetProperties(cppProperties);
return reinterpret_cast<MachDawnNativeAdapterProperties>(cppProperties);
}
MACH_EXPORT WGPUAdapter machDawnNativeAdapter_get(MachDawnNativeAdapter adapter) {
return reinterpret_cast<dawn_native::Adapter*>(adapter)->Get();
}
// TODO(dawn-native-mach):
// std::vector<const char*> GetSupportedExtensions() const;
// WGPUDeviceProperties GetAdapterProperties() const;
// bool GetLimits(WGPUSupportedLimits* limits) const;
// void SetUseTieredLimits(bool useTieredLimits);
// // Check that the Adapter is able to support importing external images. This is necessary
// // to implement the swapchain and interop APIs in Chromium.
// bool SupportsExternalImages() const;
// explicit operator bool() const;
// TODO(dawn-native-mach): These API* methods correlate to the new API (which is unified between Dawn
// and wgpu-native?), e.g. dawn_native::Instance::APIRequestAdapter corresponds to wgpuInstanceRequestAdapter
// These are not implemented in Dawn yet according to austineng, but we should switch to this API once they do:
//
// "fyi, the requestAdapter/requestedDevice stuff isn't implemented right now. We just added the interface for it, but still working on the implementation. Today, it'll always fail the callback."
//
//
// bool APIGetLimits(SupportedLimits* limits) const;
// void APIGetProperties(AdapterProperties* properties) const;
// bool APIHasFeature(wgpu::FeatureName feature) const;
// uint32_t APIEnumerateFeatures(wgpu::FeatureName* features) const;
// void APIRequestDevice(const DeviceDescriptor* descriptor,
// WGPURequestDeviceCallback callback,
// void* userdata);
//
MACH_EXPORT WGPUDevice machDawnNativeAdapter_createDevice(MachDawnNativeAdapter adapter, MachDawnNativeDawnDeviceDescriptor* deviceDescriptor) {
auto self = reinterpret_cast<dawn_native::Adapter*>(adapter);
if (deviceDescriptor == nullptr) {
return self->CreateDevice();
}
std::vector<const char*> cppRequiredExtensions;
for (int i = 0; i < deviceDescriptor->requiredFeaturesLength; i++)
cppRequiredExtensions.push_back(deviceDescriptor->requiredFeatures[i]);
std::vector<const char*> cppForceEnabledToggles;
for (int i = 0; i < deviceDescriptor->forceEnabledTogglesLength; i++)
cppForceEnabledToggles.push_back(deviceDescriptor->forceEnabledToggles[i]);
std::vector<const char*> cppForceDisabledToggles;
for (int i = 0; i < deviceDescriptor->forceDisabledTogglesLength; i++)
cppForceDisabledToggles.push_back(deviceDescriptor->forceDisabledToggles[i]);
auto cppDeviceDescriptor = dawn_native::DawnDeviceDescriptor{
.requiredFeatures = cppRequiredExtensions,
.forceEnabledToggles = cppForceEnabledToggles,
.forceDisabledToggles = cppForceDisabledToggles,
.requiredLimits = deviceDescriptor->requiredLimits,
};
return self->CreateDevice(&cppDeviceDescriptor);
}
// TODO(dawn-native-mach):
// // Create a device on this adapter, note that the interface will change to include at least
// // a device descriptor and a pointer to backend specific options.
// // On an error, nullptr is returned.
// WGPUDevice CreateDevice(const DeviceDescriptor* deviceDescriptor = nullptr);
// TODO(dawn-native-mach):
// void RequestDevice(const DeviceDescriptor* descriptor,
// WGPURequestDeviceCallback callback,
// void* userdata);
// TODO(dawn-native-mach):
// // Reset the backend device object for testing purposes.
// void ResetInternalDeviceForTesting();
// std::vector<Adapter> wrapper
typedef struct MachDawnNativeAdaptersImpl* MachDawnNativeAdapters;
MACH_EXPORT MachDawnNativeAdapter machDawnNativeAdapters_index(MachDawnNativeAdapters adapters, uintptr_t index) {
auto self = reinterpret_cast<std::vector<dawn_native::Adapter>*>(adapters);
return reinterpret_cast<MachDawnNativeAdapter>(&(*self)[index]);
}
MACH_EXPORT uintptr_t machDawnNativeAdapters_length(MachDawnNativeAdapters adapters) {
auto self = reinterpret_cast<std::vector<dawn_native::Adapter>*>(adapters);
return self->size();
};
// dawn_native::Instance wrappers
MACH_EXPORT MachDawnNativeInstance machDawnNativeInstance_init(void) {
return reinterpret_cast<MachDawnNativeInstance>(new dawn_native::Instance());
}
MACH_EXPORT void machDawnNativeInstance_deinit(MachDawnNativeInstance instance) {
delete reinterpret_cast<dawn_native::Instance*>(instance);
}
MACH_EXPORT WGPUInstance machDawnNativeInstance_get(MachDawnNativeInstance instance) {
return reinterpret_cast<dawn_native::Instance*>(instance)->Get();
}
// TODO(dawn-native-mach): These API* methods correlate to the new API (which is unified between Dawn
// and wgpu-native?), e.g. dawn_native::Instance::APIRequestAdapter corresponds to wgpuInstanceRequestAdapter
// These are not implemented in Dawn yet according to austineng, but we should switch to this API once they do:
//
// "fyi, the requestAdapter/requestedDevice stuff isn't implemented right now. We just added the interface for it, but still working on the implementation. Today, it'll always fail the callback."
//
// void APIRequestAdapter(const RequestAdapterOptions* options,
// WGPURequestAdapterCallback callback,
// void* userdata);
MACH_EXPORT void machDawnNativeInstance_discoverDefaultAdapters(MachDawnNativeInstance instance) {
dawn_native::Instance* self = reinterpret_cast<dawn_native::Instance*>(instance);
self->DiscoverDefaultAdapters();
}
MACH_EXPORT bool machDawnNativeInstance_discoverAdapters(MachDawnNativeInstance instance, WGPUBackendType backendType, const void* options) {
dawn_native::Instance* self = reinterpret_cast<dawn_native::Instance*>(instance);
switch (backendType) {
case WGPUBackendType_OpenGL:
#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
{
auto opt = reinterpret_cast<const MachDawnNativeAdapterDiscoveryOptions_OpenGL*>(options);
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions = dawn_native::opengl::AdapterDiscoveryOptions();
adapterOptions.getProc = opt->getProc;
return self->DiscoverAdapters(&adapterOptions);
}
#endif
case WGPUBackendType_OpenGLES:
#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
{
auto opt = reinterpret_cast<const MachDawnNativeAdapterDiscoveryOptions_OpenGLES*>(options);
dawn_native::opengl::AdapterDiscoveryOptionsES adapterOptions;
adapterOptions.getProc = opt->getProc;
return self->DiscoverAdapters(&adapterOptions);
}
#endif
case WGPUBackendType_WebGPU:
case WGPUBackendType_D3D11:
case WGPUBackendType_D3D12:
case WGPUBackendType_Metal:
case WGPUBackendType_Null:
case WGPUBackendType_Vulkan:
case WGPUBackendType_Force32:
return false;
}
}
MACH_EXPORT MachDawnNativeAdapters machDawnNativeInstance_getAdapters(MachDawnNativeInstance instance) {
dawn_native::Instance* self = reinterpret_cast<dawn_native::Instance*>(instance);
auto cppAdapters = self->GetAdapters();
auto heapAllocated = new std::vector<dawn_native::Adapter>();
for (int i=0; i<cppAdapters.size(); i++) heapAllocated->push_back(cppAdapters[i]);
return reinterpret_cast<MachDawnNativeAdapters>(heapAllocated);
}
MACH_EXPORT const DawnProcTable* machDawnNativeGetProcs() {
return &dawn_native::GetProcs();
}
// TODO(dawn-native-mach):
// const ToggleInfo* GetToggleInfo(const char* toggleName);
// TODO(dawn-native-mach):
// // Enables backend validation layers
// void EnableBackendValidation(bool enableBackendValidation);
// void SetBackendValidationLevel(BackendValidationLevel validationLevel);
// TODO(dawn-native-mach):
// // Enable debug capture on Dawn startup
// void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
// TODO(dawn-native-mach):
// void SetPlatform(dawn_platform::Platform* platform);
// typedef struct MachUtilsBackendBindingImpl* MachUtilsBackendBinding;
//
// This is a legacy method. If using OpenGL, it must be used to create a backend binding
// as Dawn does not yet support the WGPUSurface API for OpenGL yet. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2
MACH_EXPORT MachUtilsBackendBinding machUtilsCreateBinding(WGPUBackendType backendType, GLFWwindow* window, WGPUDevice device) {
wgpu::BackendType cppBackendType;
switch (backendType) {
case WGPUBackendType_WebGPU:
cppBackendType = wgpu::BackendType::WebGPU;
break;
case WGPUBackendType_D3D11:
cppBackendType = wgpu::BackendType::D3D11;
break;
case WGPUBackendType_D3D12:
cppBackendType = wgpu::BackendType::D3D12;
break;
case WGPUBackendType_Metal:
cppBackendType = wgpu::BackendType::Metal;
break;
case WGPUBackendType_Null:
cppBackendType = wgpu::BackendType::Null;
break;
case WGPUBackendType_OpenGL:
cppBackendType = wgpu::BackendType::OpenGL;
break;
case WGPUBackendType_OpenGLES:
cppBackendType = wgpu::BackendType::OpenGLES;
break;
case WGPUBackendType_Vulkan:
cppBackendType = wgpu::BackendType::Vulkan;
break;
case WGPUBackendType_Force32:
// Force32 is just to force the size of the C enum type to 32-bits, so this is technically
// an illegal input.
cppBackendType = wgpu::BackendType::Null;
break;
}
return reinterpret_cast<MachUtilsBackendBinding>(utils::CreateBinding(cppBackendType, window, device));
}
// This is a legacy method. If using OpenGL, it must be used to create a backend binding
// as Dawn does not yet support the WGPUSurface API for OpenGL yet. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2
MACH_EXPORT uint64_t machUtilsBackendBinding_getSwapChainImplementation(MachUtilsBackendBinding binding) {
auto self = reinterpret_cast<utils::BackendBinding*>(binding);
return self->GetSwapChainImplementation();
}
// This is a legacy method. If using OpenGL, it must be used to create a backend binding
// as Dawn does not yet support the WGPUSurface API for OpenGL yet. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2
MACH_EXPORT WGPUTextureFormat machUtilsBackendBinding_getPreferredSwapChainTextureFormat(MachUtilsBackendBinding binding) {
auto self = reinterpret_cast<utils::BackendBinding*>(binding);
return self->GetPreferredSwapChainTextureFormat();
}
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -1,120 +0,0 @@
#ifndef MACH_DAWNNATIVE_C_H_
#define MACH_DAWNNATIVE_C_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MACH_DAWNNATIVE_C_SHARED_LIBRARY)
# if defined(_WIN32)
# if defined(MACH_DAWNNATIVE_C_IMPLEMENTATION)
# define MACH_EXPORT __declspec(dllexport)
# else
# define MACH_EXPORT __declspec(dllimport)
# endif
# else // defined(_WIN32)
# if defined(MACH_DAWNNATIVE_C_IMPLEMENTATION)
# define MACH_EXPORT __attribute__((visibility("default")))
# else
# define MACH_EXPORT
# endif
# endif // defined(_WIN32)
#else // defined(MACH_DAWNNATIVE_C_SHARED_LIBRARY)
# define MACH_EXPORT
#endif // defined(MACH_DAWNNATIVE_C_SHARED_LIBRARY)
#include <dawn/webgpu.h>
#include <dawn/dawn_proc_table.h>
// TODO(slimsag): future: Dawn authors want dawn_native::AdapterProperties to eventually be in webgpu.h,
// and there is a corresponding WGPUAdapterProperties struct today, but there aren't corresponding methods
// to actually use / work with it today.
typedef struct MachDawnNativeAdapterPropertiesImpl* MachDawnNativeAdapterProperties;
MACH_EXPORT void machDawnNativeAdapterProperties_deinit(MachDawnNativeAdapterProperties properties);
MACH_EXPORT uint32_t machDawnNativeAdapterProperties_getVendorID(MachDawnNativeAdapterProperties properties);
MACH_EXPORT uint32_t machDawnNativeAdapterProperties_getDeviceID(MachDawnNativeAdapterProperties properties);
MACH_EXPORT char const* machDawnNativeAdapterProperties_getName(MachDawnNativeAdapterProperties properties);
MACH_EXPORT char const* machDawnNativeAdapterProperties_getDriverDescription(MachDawnNativeAdapterProperties properties);
MACH_EXPORT WGPUAdapterType machDawnNativeAdapterProperties_getAdapterType(MachDawnNativeAdapterProperties properties);
MACH_EXPORT WGPUBackendType machDawnNativeAdapterProperties_getBackendType(MachDawnNativeAdapterProperties properties);
// An adapter is an object that represent on possibility of creating devices in the system.
// Most of the time it will represent a combination of a physical GPU and an API. Not that the
// same GPU can be represented by multiple adapters but on different APIs.
//
// The underlying Dawn adapter is owned by the Dawn instance so this is just a reference to an
// underlying adapter.
typedef struct MachDawnNativeAdapterImpl* MachDawnNativeAdapter;
MACH_EXPORT WGPUAdapter machDawnNativeAdapter_get(MachDawnNativeAdapter adapter);
MACH_EXPORT MachDawnNativeAdapterProperties machDawnNativeAdapter_getProperties(MachDawnNativeAdapter adapter);
// An optional parameter of Adapter::CreateDevice() to send additional information when creating
// a Device. For example, we can use it to enable a workaround, optimization or feature.
typedef struct MachDawnNativeDawnDeviceDescriptor {
char** requiredFeatures;
uintptr_t requiredFeaturesLength;
char** forceEnabledToggles;
uintptr_t forceEnabledTogglesLength;
char** forceDisabledToggles;
uintptr_t forceDisabledTogglesLength;
// default null
WGPURequiredLimits* requiredLimits;
} MachDawnNativeDawnDeviceDescriptor;
MACH_EXPORT WGPUDevice machDawnNativeAdapter_createDevice(MachDawnNativeAdapter adapter, MachDawnNativeDawnDeviceDescriptor* deviceDescriptor);
typedef struct MachDawnNativeAdaptersImpl* MachDawnNativeAdapters;
MACH_EXPORT MachDawnNativeAdapter machDawnNativeAdapters_index(MachDawnNativeAdapters adapters, uintptr_t index);
MACH_EXPORT uintptr_t machDawnNativeAdapters_length(MachDawnNativeAdapters adapters);
// Represents a connection to dawn_native and is used for dependency injection, discovering
// system adapters and injecting custom adapters (like a Swiftshader Vulkan adapter).
//
// This can be initialized via machDawnNativeInstanceInit and destroyed via
// machDawnNativeInstanceDeinit. The instance controls the lifetime of all adapters for the
// instance.
typedef struct MachDawnNativeInstanceImpl* MachDawnNativeInstance;
MACH_EXPORT MachDawnNativeInstance machDawnNativeInstance_init(void);
MACH_EXPORT void machDawnNativeInstance_deinit(MachDawnNativeInstance);
MACH_EXPORT WGPUInstance machDawnNativeInstance_get(MachDawnNativeInstance instance);
MACH_EXPORT void machDawnNativeInstance_discoverDefaultAdapters(MachDawnNativeInstance);
// Adds adapters that can be discovered with the options provided (like a getProcAddress).
// You must specify a valid backend type corresponding to the type of MachDawnNativeAdapterDiscoveryOptions_
// struct pointer you pass as options.
// Returns true on success.
MACH_EXPORT bool machDawnNativeInstance_discoverAdapters(MachDawnNativeInstance instance, WGPUBackendType backendType, const void* options);
MACH_EXPORT MachDawnNativeAdapters machDawnNativeInstance_getAdapters(MachDawnNativeInstance instance);
// Backend-agnostic API for dawn_native
MACH_EXPORT const DawnProcTable* machDawnNativeGetProcs();
// Backend-specific options which can be passed to discoverAdapters
typedef struct MachDawnNativeAdapterDiscoveryOptions_OpenGL {
void* (*getProc)(const char*);
} MachDawnNativeAdapterDiscoveryOptions_OpenGL;
typedef struct MachDawnNativeAdapterDiscoveryOptions_OpenGLES {
void* (*getProc)(const char*);
} MachDawnNativeAdapterDiscoveryOptions_OpenGLES;
// utils
//
// These are legacy methods. If using OpenGL, they must be used to create a backend binding
// as Dawn does not yet support the WGPUSurface API for OpenGL yet. https://bugs.chromium.org/p/dawn/issues/detail?id=269&q=surface&can=2
#include <GLFW/glfw3.h>
typedef struct MachUtilsBackendBindingImpl* MachUtilsBackendBinding;
MACH_EXPORT MachUtilsBackendBinding machUtilsCreateBinding(WGPUBackendType backendType, GLFWwindow* window, WGPUDevice device);
MACH_EXPORT uint64_t machUtilsBackendBinding_getSwapChainImplementation(MachUtilsBackendBinding binding);
MACH_EXPORT WGPUTextureFormat machUtilsBackendBinding_getPreferredSwapChainTextureFormat(MachUtilsBackendBinding binding);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // MACH_DAWNNATIVE_C_H_