Skip to content

Commit

Permalink
Support for async methods (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Jul 12, 2024
1 parent bd1914a commit 2e79410
Show file tree
Hide file tree
Showing 42 changed files with 324 additions and 78 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "externals/dawn"]
path = externals/dawn
url = https://dawn.googlesource.com/dawn
branch = chromium/6539
branch = chromium/6589
5 changes: 4 additions & 1 deletion package/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "react-native-wcandillon"
"extends": "react-native-wcandillon",
"rules": {
"no-bitwise": "off"
}
}
7 changes: 1 addition & 6 deletions package/cpp/rnwgpu/RNWebGPUManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ RNWebGPUManager::RNWebGPUManager(
std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker)
: _jsRuntime(jsRuntime), _jsCallInvoker(jsCallInvoker) {

wgpu::InstanceDescriptor instanceDesc;
instanceDesc.features.timedWaitAnyEnable = true;
instanceDesc.features.timedWaitAnyMaxCount = 64;
auto instance = wgpu::CreateInstance(&instanceDesc);
auto gpu =
std::make_shared<GPU>(std::move(instance));
auto gpu = std::make_shared<GPU>();

auto bufferUsage = std::make_shared<GPUBufferUsage>();
_jsRuntime->global().setProperty(
Expand Down
34 changes: 34 additions & 0 deletions package/cpp/rnwgpu/api/AsyncRunner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "webgpu/webgpu_cpp.h"

#include <future>
#include <utility>

namespace rnwgpu {

class AsyncRunner {
public:
explicit AsyncRunner(wgpu::Instance *instance) : instance(instance) {}

template <typename Func>
auto runAsync(Func &&func) -> std::future<std::invoke_result_t<Func>> {
using ReturnType = std::invoke_result_t<Func>;
return std::async(std::launch::async,
[this, func = std::forward<Func>(func)]() -> ReturnType {
if constexpr (std::is_void_v<ReturnType>) {
func();
instance->ProcessEvents();
} else {
auto result = func();
instance->ProcessEvents();
return result;
}
});
}

private:
wgpu::Instance *instance;
};

} // namespace rnwgpu
26 changes: 25 additions & 1 deletion package/cpp/rnwgpu/api/GPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,34 @@ GPU::requestAdapter(std::shared_ptr<GPURequestAdapterOptions> options) {
throw std::runtime_error("Failed to request adapter");
}

return std::make_shared<GPUAdapter>(std::move(adapter));
return std::make_shared<GPUAdapter>(std::move(adapter), _async);
});
}

// Async impl keeping here as a reference
// std::future<std::shared_ptr<GPUAdapter>>
// GPU::requestAdapter(std::shared_ptr<GPURequestAdapterOptions> options) {
// return _async->runAsync([=] {
// auto aOptions = options->getInstance();
// wgpu::Adapter adapter = nullptr;
// auto result = std::make_shared<GPUAdapter>(adapter, _async);
// wgpu::RequestAdapterCallbackInfo callback;
// callback.callback = [](WGPURequestAdapterStatus, WGPUAdapter cAdapter,
// const char *message, void *userdata) {
// if (message != nullptr) {
// fprintf(stderr, "%s", message);
// return;
// }
// *static_cast<wgpu::Adapter *>(userdata) =
// wgpu::Adapter::Acquire(cAdapter);
// };
// callback.mode = wgpu::CallbackMode::AllowProcessEvents;
// callback.userdata = &(result->_instance);
// _instance.RequestAdapter(aOptions, callback);
// return result;
// });
//}

wgpu::TextureFormat GPU::getPreferredCanvasFormat() {
#if defined(__ANDROID__)
return wgpu::TextureFormat::RGBA8Unorm;
Expand Down
13 changes: 11 additions & 2 deletions package/cpp/rnwgpu/api/GPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand All @@ -20,8 +22,14 @@ namespace m = margelo;

class GPU : public m::HybridObject {
public:
explicit GPU(wgpu::Instance instance)
: HybridObject("GPU"), _instance(instance) {}
GPU() : HybridObject("GPU") {
wgpu::InstanceDescriptor instanceDesc;
instanceDesc.features.timedWaitAnyEnable = true;
instanceDesc.features.timedWaitAnyMaxCount = 64;
_instance = wgpu::CreateInstance(&instanceDesc);
auto instance = &_instance;
_async = std::make_shared<AsyncRunner>(instance);
}

public:
std::string getBrand() { return _name; }
Expand All @@ -39,5 +47,6 @@ class GPU : public m::HybridObject {

private:
wgpu::Instance _instance;
std::shared_ptr<AsyncRunner> _async;
};
} // namespace rnwgpu
3 changes: 2 additions & 1 deletion package/cpp/rnwgpu/api/GPUAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ GPUAdapter::requestDevice(std::shared_ptr<GPUDeviceDescriptor> descriptor) {
if (!device) {
throw std::runtime_error("Failed to request device");
}
return std::make_shared<GPUDevice>(std::move(device), descriptor->label);
return std::make_shared<GPUDevice>(std::move(device), _async,
descriptor->label);
});
}

Expand Down
9 changes: 7 additions & 2 deletions package/cpp/rnwgpu/api/GPUAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand All @@ -20,8 +22,9 @@ namespace m = margelo;

class GPUAdapter : public m::HybridObject {
public:
explicit GPUAdapter(wgpu::Adapter instance)
: HybridObject("GPUAdapter"), _instance(instance) {}
explicit GPUAdapter(wgpu::Adapter instance,
std::shared_ptr<AsyncRunner> async)
: HybridObject("GPUAdapter"), _instance(instance), _async(async) {}

public:
std::string getBrand() { return _name; }
Expand All @@ -36,5 +39,7 @@ class GPUAdapter : public m::HybridObject {

private:
wgpu::Adapter _instance;
std::shared_ptr<AsyncRunner> _async;
friend class GPU;
};
} // namespace rnwgpu
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUAdapterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUBindGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUBindGroupLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
57 changes: 29 additions & 28 deletions package/cpp/rnwgpu/api/GPUBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,43 @@ GPUBuffer::getMappedRange(std::optional<size_t> o, std::optional<size_t> size) {
throw std::runtime_error("Failed to map buffer");
}
auto buffer = std::make_shared<MutableJSIBuffer>(ptr, s);
//mappings.emplace_back(Mapping{start, end, buffer});
// mappings.emplace_back(Mapping{start, end, buffer});
return buffer;
}

std::future<void> GPUBuffer::mapAsync(size_t mode, std::optional<size_t> o,
std::optional<size_t> size) {
auto md = static_cast<wgpu::MapMode>(mode);
uint64_t offset = o.value_or(0);
uint64_t s = size.has_value() ? size.value() : (_instance.GetSize() - offset);
uint64_t start = offset;
uint64_t end = offset + s;

std::promise<void> promise;
std::future<void> future = promise.get_future();
return _async->runAsync([=] {
auto md = static_cast<wgpu::MapMode>(mode);
uint64_t offset = o.value_or(0);
uint64_t s =
size.has_value() ? size.value() : (_instance.GetSize() - offset);
uint64_t start = offset;
uint64_t end = offset + s;

// for (auto& mapping : mappings) {
// if (mapping.Intersects(start, end)) {
// promise.set_exception(std::make_exception_ptr(std::runtime_error("Buffer is already mapped")));
// return future;
// }
// }

_instance.MapAsync(md, offset, s, [](WGPUBufferMapAsyncStatus status, void* userdata) {
auto pPromise = static_cast<std::promise<void> *>(userdata);
switch (status) {
// for (auto& mapping : mappings) {
// if (mapping.Intersects(start, end)) {
// promise.set_exception(std::make_exception_ptr(std::runtime_error("Buffer
// is already mapped"))); return future;
// }
// }
wgpu::BufferMapCallbackInfo callback;
callback.mode = wgpu::CallbackMode::AllowProcessEvents;
callback.callback = [](WGPUBufferMapAsyncStatus status, void *userdata) {
switch (status) {
case WGPUBufferMapAsyncStatus_Success:
pPromise->set_value();
break;
break;
case WGPUBufferMapAsyncStatus_ValidationError:
throw std::runtime_error("WGPUBufferMapAsyncStatus_ValidationError");
break;
default:
pPromise->set_exception(std::make_exception_ptr(std::runtime_error("WGPUBufferMapAsyncStatus: " + std::to_string(status))));
break;
delete pPromise;
}
}, new std::promise<void>(std::move(promise)));

return future;
throw std::runtime_error("WGPUBufferMapAsyncStatus: " +
std::to_string(status));
break;
}
};
_instance.MapAsync(md, offset, s, callback);
});
}

void GPUBuffer::unmap() { _instance.Unmap(); }
Expand Down
12 changes: 8 additions & 4 deletions package/cpp/rnwgpu/api/GPUBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand All @@ -18,13 +19,15 @@ namespace m = margelo;

class GPUBuffer : public m::HybridObject {
public:
explicit GPUBuffer(wgpu::Buffer instance, std::string label)
: HybridObject("GPUBuffer"), _instance(instance), _label(label) {}
explicit GPUBuffer(wgpu::Buffer instance, std::shared_ptr<AsyncRunner> async,
std::string label)
: HybridObject("GPUBuffer"), _instance(instance), _async(async),
_label(label) {}

public:
std::string getBrand() { return _name; }

std::future<void> mapAsync(size_t mode, std::optional<size_t> offset,
std::future<void> mapAsync(uint64_t mode, std::optional<size_t> offset,
std::optional<size_t> size);
std::shared_ptr<MutableJSIBuffer> getMappedRange(std::optional<size_t> offset,
std::optional<size_t> size);
Expand All @@ -49,6 +52,7 @@ class GPUBuffer : public m::HybridObject {

private:
wgpu::Buffer _instance;
std::shared_ptr<AsyncRunner> _async;
std::string _label;
struct Mapping {
uint64_t start;
Expand All @@ -60,4 +64,4 @@ class GPUBuffer : public m::HybridObject {
};
std::vector<Mapping> mappings;
};
} // namespace rnwgpu
} // namespace rnwgpu
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUCanvasContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUCommandBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUCommandEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUCompilationInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
2 changes: 2 additions & 0 deletions package/cpp/rnwgpu/api/GPUCompilationMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
#include <future>
#include <memory>
#include <string>
#include <vector>

#include "Unions.h"
#include <RNFHybridObject.h>

#include "AsyncRunner.h"
#include "MutableBuffer.h"

#include "webgpu/webgpu_cpp.h"
Expand Down
Loading

0 comments on commit 2e79410

Please sign in to comment.