forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP] layered webgpu.h implementation prototype
- Loading branch information
Showing
9 changed files
with
339 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,7 @@ | |
'libnoexit', | ||
'sqlite3', | ||
'sqlite3-mt', | ||
'libwebgpu', | ||
'libwebgpu_cpp', | ||
] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/** | ||
* @license | ||
* Copyright 2023 The Emscripten Authors | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
/* | ||
* WebGPU support. | ||
* FIXME: WRITE SOME DOCUMENTATION | ||
*/ | ||
|
||
{{{ | ||
// Helper functions for code generation | ||
global.gpu = { | ||
// Must be in sync with webgpu.h. | ||
COPY_STRIDE_UNDEFINED: 0xFFFFFFFF, | ||
LIMIT_U32_UNDEFINED: 0xFFFFFFFF, | ||
MIP_LEVEL_COUNT_UNDEFINED: 0xFFFFFFFF, | ||
ARRAY_LAYER_COUNT_UNDEFINED: 0xFFFFFFFF, | ||
AdapterType: { | ||
Unknown: 3, | ||
}, | ||
BackendType: { | ||
WebGPU: 1, | ||
}, | ||
BufferMapAsyncStatus: { | ||
Success: 0, | ||
ValidationError: 1, | ||
Unknown: 2, | ||
DeviceLost: 3, | ||
DestroyedBeforeCallback: 4, | ||
UnmappedBeforeCallback: 5, | ||
MappingAlreadyPending: 6, | ||
OffsetOutOfRange: 7, | ||
SizeOutOfRange: 8, | ||
}, | ||
CallbackFlag: { | ||
WaitAnyOnly: 0, | ||
AllowProcessEvents: 1, | ||
AllowSpontaneous: 2, | ||
}, | ||
CompilationInfoRequestStatus: { | ||
Success: 0, | ||
Error: 1, | ||
DeviceLost: 2, | ||
Unknown: 3, | ||
}, | ||
CreatePipelineAsyncStatus: { | ||
Success: 0, | ||
ValidationError: 1, | ||
InternalError: 2, | ||
DeviceLost: 3, | ||
DeviceDestroyed: 4, | ||
Unknown: 5, | ||
}, | ||
ErrorType: { | ||
NoError: 0, | ||
Validation: 1, | ||
OutOfMemory: 2, | ||
Unknown: 3, | ||
}, | ||
PresentMode: { | ||
Fifo: 2, | ||
}, | ||
LoadOp: { | ||
Undefined: 0, | ||
Clear: 1, | ||
Load: 2, | ||
}, | ||
StoreOp: { | ||
Undefined: 0, | ||
Store: 1, | ||
Discard: 2, | ||
}, | ||
MapMode: { | ||
None: 0, | ||
Read: 1, | ||
Write: 2 | ||
}, | ||
RequestAdapterStatus: { | ||
Success: 0, | ||
Unavailable: 1, | ||
Error: 2, | ||
}, | ||
RequestDeviceStatus: { | ||
Success: 0, | ||
Error: 1, | ||
}, | ||
SType: { | ||
SurfaceDescriptorFromCanvasHTMLSelector: 4, | ||
ShaderModuleSPIRVDescriptor: 5, | ||
ShaderModuleWGSLDescriptor: 6, | ||
PrimitiveDepthClipControl: 7, | ||
RenderPassDescriptorMaxDrawCount: 15, | ||
}, | ||
QueueWorkDoneStatus: { | ||
Success: 0, | ||
Error: 1, | ||
}, | ||
TextureFormat: { | ||
Undefined: 0, | ||
}, | ||
VertexStepMode: { | ||
Vertex: 0, | ||
Instance: 1, | ||
VertexBufferNotUsed: 2, | ||
}, | ||
WaitStatus: { | ||
Success: 0, | ||
TimedOut: 1, | ||
UnsupportedTimeout: 2, | ||
UnsupportedCount: 3, | ||
UnsupportedMixedSources: 4, | ||
}, | ||
}; | ||
null; | ||
}}} | ||
|
||
var LibraryEmWebGPU = { | ||
$EmWebGPU: { | ||
PowerPreference: [undefined, 'low-power', 'high-performance'], | ||
_tableNextID: 1, | ||
_table: [], | ||
tableInsert: value => { | ||
const id = EmWebGPU._tableNextID++; | ||
EmWebGPU._table[id] = value; | ||
return id; | ||
}, | ||
}, | ||
|
||
emwgpuSetLabel: (id, label) => { | ||
EmWebGPU.table[id]['label'] = UTF8ToString(label); | ||
}, | ||
emwgpuDestroy: (id) => { | ||
EmWebGPU.table[id]['destroy'](); | ||
}, | ||
emwgpuDelete: (id) => { | ||
delete EmWebGPU.table[id]; | ||
}, | ||
|
||
emwgpuRequestAdapter__deps: ['emwgpuOnRequestAdapter'], | ||
emwgpuRequestAdapter: (request, powerPreference, forceFallbackAdapter) => { | ||
if (!('gpu' in navigator)) { | ||
_emwgpuOnRequestAdapter(request, 0, {{{ gpu.RequestAdapterStatus.Unavailable }}}); | ||
return; | ||
} | ||
|
||
{{{ runtimeKeepalivePush() }}} | ||
navigator["gpu"]["requestAdapter"]({ | ||
powerPreference: EmWebGPU.PowerPreference[powerPreference], | ||
forceFallbackAdapter, | ||
}).then(adapter => { | ||
{{{ runtimeKeepalivePop() }}} | ||
if (adapter) { | ||
_emwgpuOnRequestAdapter(request, EmWebGPU.tableInsert(adapter), {{{ gpu.RequestAdapterStatus.Success }}}); | ||
} else { | ||
_emwgpuOnRequestAdapter(request, 0, {{{ gpu.RequestAdapterStatus.Unavailable }}}); | ||
} | ||
}, exception => { | ||
{{{ runtimeKeepalivePop() }}} | ||
_emwgpuOnRequestAdapter(request, 0, {{{ gpu.RequestAdapterStatus.Error }}}); | ||
}); | ||
}, | ||
}; | ||
|
||
autoAddDeps(LibraryEmWebGPU, '$EmWebGPU'); | ||
addToLibrary(LibraryEmWebGPU); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/** | ||
* @license | ||
* Copyright 2023 The Emscripten Authors | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
/* | ||
* Implementation of webgpu.h + html5_webgpu.h over library_emwebgpu.js. | ||
*/ | ||
|
||
#include <webgpu/webgpu.h> | ||
|
||
#include <atomic> | ||
#include <cassert> | ||
#include <cstdint> | ||
|
||
// FIXME | ||
#include <cstdio> | ||
|
||
using ObjID = uint64_t; | ||
struct AdapterRequest; | ||
|
||
// Declarations for library_emwebgpu.js | ||
extern "C" { | ||
|
||
void emwgpuSetLabel(ObjID id, const char* label); | ||
void emwgpuDestroy(ObjID id); | ||
void emwgpuDelete(ObjID id); | ||
|
||
using WGPUBool = int32_t; | ||
void emwgpuRequestAdapter(AdapterRequest* request, WGPUPowerPreference powerPreference, WGPUBool forceFallbackAdapter); | ||
|
||
|
||
// Implementation helpers | ||
|
||
#define DEFINE_REF_RELEASE(Name) \ | ||
void wgpu##Name##Reference(WGPU##Name o) { o->Reference(); } \ | ||
void wgpu##Name##Release(WGPU##Name o) { o->Release(); } | ||
|
||
class ManuallyRefCounted { | ||
public: | ||
ManuallyRefCounted() = default; | ||
virtual ~ManuallyRefCounted() = default; | ||
|
||
void Reference() { | ||
++mRefCount; | ||
} | ||
void Release() { | ||
uint64_t newRefCount = --mRefCount; | ||
if (newRefCount == 0) { | ||
OnBeforeDelete(); | ||
delete this; | ||
} | ||
} | ||
protected: | ||
virtual void OnBeforeDelete() {} | ||
std::atomic<uint64_t> mRefCount{1}; | ||
private: | ||
// Non-copyable | ||
ManuallyRefCounted(const ManuallyRefCounted&) = delete; | ||
void operator=(const ManuallyRefCounted&) = delete; | ||
}; | ||
|
||
class ObjectFromInstance : public ManuallyRefCounted { | ||
public: | ||
ObjectFromInstance(WGPUInstance instance, ObjID id) | ||
: mInstance(instance), mHandle(id) { | ||
wgpuInstanceReference(mInstance); | ||
} | ||
virtual ~ObjectFromInstance() override { | ||
emwgpuDelete(mHandle); | ||
} | ||
private: | ||
WGPUInstance mInstance; | ||
ObjID mHandle; | ||
}; | ||
|
||
struct AdapterRequest { | ||
WGPUInstance instance; | ||
WGPURequestAdapterCallback callback; | ||
void* userdata; | ||
}; | ||
|
||
// WGPU object definitions | ||
|
||
struct WGPUInstanceImpl : public ManuallyRefCounted {}; | ||
|
||
struct WGPUAdapterImpl : public ObjectFromInstance { | ||
using ObjectFromInstance::ObjectFromInstance; | ||
}; | ||
|
||
|
||
// Implementations for JS->WASM calls back from library_emwebgpu.js | ||
|
||
void emwgpuOnRequestAdapter(AdapterRequest* request, ObjID adapterHandle, WGPURequestAdapterStatus status) { | ||
WGPUAdapter adapter = nullptr; | ||
const char* message = nullptr; | ||
if (status == 0) { | ||
assert(adapterHandle); | ||
adapter = new WGPUAdapterImpl(request->instance, adapterHandle); | ||
} else { | ||
message = "failed"; | ||
} | ||
request->callback(status, adapter, message, request->userdata); | ||
wgpuInstanceRelease(request->instance); | ||
delete request; | ||
} | ||
|
||
// Standalone functions | ||
|
||
WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor const * descriptor) { | ||
return new WGPUInstanceImpl(); | ||
} | ||
|
||
// Methods of Instance | ||
|
||
DEFINE_REF_RELEASE(Instance); | ||
|
||
void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPURequestAdapterOptions const * options, WGPURequestAdapterCallback callback, void * userdata) { | ||
wgpuInstanceReference(instance); | ||
auto* request = new AdapterRequest{instance, callback, userdata}; | ||
WGPUPowerPreference powerPreference = WGPUPowerPreference_Undefined; | ||
WGPUBool forceFallbackAdapter = false; | ||
if (options) { | ||
powerPreference = options->powerPreference; | ||
forceFallbackAdapter = options->forceFallbackAdapter; | ||
} | ||
emwgpuRequestAdapter(request, powerPreference, forceFallbackAdapter); | ||
} | ||
|
||
// FIXME | ||
|
||
void wgpuBufferRelease(WGPUBuffer) {} | ||
WGPUBuffer wgpuDeviceCreateBuffer(WGPUDevice, WGPUBufferDescriptor const *) { | ||
return nullptr; | ||
} | ||
void wgpuDeviceRelease(WGPUDevice) {} | ||
|
||
} // extern "C" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#include <webgpu/webgpu.h> | ||
#include <cstdio> | ||
|
||
void OnRequestAdapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void*) { | ||
printf("Got! status=%d adapter=%p message=%s\n", status, adapter, message); | ||
} | ||
|
||
int main() { | ||
WGPUInstance instance = wgpuCreateInstance(nullptr); | ||
wgpuInstanceRequestAdapter(instance, nullptr, OnRequestAdapter, nullptr); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters