Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,16 @@ A Vulkan implementation is found by CMake in the following priority order:
### Using Dawn as a backend

We assume you have built [Dawn][Dawn] from source, and have access to both the
source and build trees. To build a Dawn backend for Amber, set the following
CMake variables when configuring Amber:

* `Dawn_INCLUDE_DIR`: The directory containing `dawn/dawn_export.h`
(in the source tree).
* `Dawn_GEN_INCLUDE_DIR`: The directory containing generated header
`dawn/dawncpp.h` (in the build output tree).
* `Dawn_LIBRARY_DIR`: The directory containing the `dawn_native` library (in
the build output tree).
source and build trees. To build a Dawn backend for Amber, build Dawn
as a monolithic shared library with `-DDAWN_BUILD_MONOLITHIC_LIBRARY=ON`. Then
when configuring Amber, set the following CMake variables:

* `Dawn_INCLUDE_DIR`: The directory containing `webgpu/webgpu.h`
(e.g., `<dawn_src>/include`).
* `Dawn_GEN_INCLUDE_DIR`: The directory containing generated headers like
`dawn/webgpu_cpp.h` (e.g., `<dawn_out>/gen/include`).
* `Dawn_LIBRARY_DIR`: The directory containing the `webgpu_dawn` library
(e.g., `<dawn_out>`).

### Using SwiftShader as a backend

Expand Down
7 changes: 5 additions & 2 deletions include/amber/amber_dawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@
#ifndef AMBER_AMBER_DAWN_H_
#define AMBER_AMBER_DAWN_H_

#include <webgpu/webgpu_cpp.h>
#include "amber/amber.h"
#include "dawn/dawncpp.h"

namespace amber {

/// Configuration for the Dawn engine.
struct DawnEngineConfig : public EngineConfig {
~DawnEngineConfig() override;

/// The Dawn Instance to use.
wgpu::Instance instance;

/// The Dawn Device to use for running tests.
::dawn::Device* device;
wgpu::Device device;
};

} // namespace amber
Expand Down
2 changes: 1 addition & 1 deletion samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ endif()

if (${Dawn_FOUND})
set(AMBER_SOURCES ${AMBER_SOURCES} config_helper_dawn.cc)
list(APPEND AMBER_EXTRA_LIBS Dawn::dawn_native Dawn::dawn)
list(APPEND AMBER_EXTRA_LIBS Dawn::dawn)
if (APPLE)
add_definitions(-DAMBER_DAWN_METAL=1)
find_library(METAL_LIB Metal)
Expand Down
116 changes: 93 additions & 23 deletions samples/config_helper_dawn.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "samples/config_helper_dawn.h"

#include <iostream>
#include <utility>

namespace sample {

Expand All @@ -24,26 +25,52 @@ ConfigHelperDawn::~ConfigHelperDawn() = default;
namespace {

// Callback which prints a message from a Dawn device operation.
void PrintDeviceError(DawnErrorType errorType, const char* message, void*) {
void PrintDeviceError(wgpu::Device const& /* device */,
wgpu::ErrorType errorType,
wgpu::StringView message) {
switch (errorType) {
case DAWN_ERROR_TYPE_VALIDATION:
case wgpu::ErrorType::Validation:
std::cout << "Validation ";
break;
case DAWN_ERROR_TYPE_OUT_OF_MEMORY:
case wgpu::ErrorType::OutOfMemory:
std::cout << "Out of memory ";
break;
case DAWN_ERROR_TYPE_UNKNOWN:
case DAWN_ERROR_TYPE_FORCE32:
std::cout << "Unknown ";
case wgpu::ErrorType::Internal:
std::cout << "Internal ";
break;
case DAWN_ERROR_TYPE_DEVICE_LOST:
std::cout << "Device lost ";
case wgpu::ErrorType::Unknown:
std::cout << "Unknown ";
break;
default:
std::cout << "Unreachable";
return;
}
std::cout << "error: " << message << std::endl;
std::cout << "error: " << (message.data ? message.data : "unknown error")
<< std::endl;
}

// Callback which prints a message when the Dawn device is lost.
void HandleDeviceLost(wgpu::Device const& /* device */,
wgpu::DeviceLostReason reason,
wgpu::StringView message) {
std::cout << "Device lost ";
switch (reason) {
case wgpu::DeviceLostReason::Destroyed:
std::cout << "(Destroyed) ";
break;
case wgpu::DeviceLostReason::CallbackCancelled:
std::cout << "(Callback Cancelled) ";
break;
case wgpu::DeviceLostReason::FailedCreation:
std::cout << "(Failed Creation) ";
break;
case wgpu::DeviceLostReason::Unknown:
default:
std::cout << "(Unknown) ";
break;
}
std::cout << "error: " << (message.data ? message.data : "unknown error")
<< std::endl;
}

} // namespace
Expand All @@ -59,31 +86,74 @@ amber::Result ConfigHelperDawn::CreateConfig(
bool,
bool,
std::unique_ptr<amber::EngineConfig>* config) {
// Set procedure table and error callback.
DawnProcTable backendProcs = dawn_native::GetProcs();
dawnSetProcs(&backendProcs);
dawn_instance_.DiscoverDefaultAdapters();
const char* allow_unsafe_apis = "allow_unsafe_apis";
wgpu::DawnTogglesDescriptor toggles;
Comment thread
dj2 marked this conversation as resolved.
toggles.enabledToggleCount = 1;
toggles.enabledToggles = &allow_unsafe_apis;

wgpu::InstanceFeatureName required_features[] = {
wgpu::InstanceFeatureName::ShaderSourceSPIRV};
wgpu::InstanceDescriptor instance_desc;
instance_desc.nextInChain = &toggles;
instance_desc.requiredFeatureCount = 1;
instance_desc.requiredFeatures = required_features;
dawn_instance_ = wgpu::CreateInstance(&instance_desc);

for (dawn_native::Adapter& adapter : dawn_instance_.GetAdapters()) {
if (!dawn_instance_) {
return amber::Result("could not create Dawn instance");
}

wgpu::RequestAdapterOptions adapter_options;
#if AMBER_DAWN_METAL
::dawn_native::BackendType backendType = ::dawn_native::BackendType::Metal;
adapter_options.backendType = wgpu::BackendType::Metal;
#else // assuming VULKAN
::dawn_native::BackendType backendType = ::dawn_native::BackendType::Vulkan;
adapter_options.backendType = wgpu::BackendType::Vulkan;
#endif

if (adapter.GetBackendType() == backendType) {
dawn_device_ = ::dawn::Device::Acquire(adapter.CreateDevice());
}
struct RequestAdapterData {
wgpu::Adapter adapter = nullptr;
bool completed = false;
} adapter_data;

dawn_instance_.RequestAdapter(
&adapter_options, wgpu::CallbackMode::AllowProcessEvents,
[](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter,
wgpu::StringView message, RequestAdapterData* data) {
if (status == wgpu::RequestAdapterStatus::Success) {
data->adapter = std::move(adapter);
} else {
std::cerr << "RequestAdapter failed: "
<< (message.data ? message.data : "unknown error")
<< std::endl;
}
data->completed = true;
},
&adapter_data);

while (!adapter_data.completed) {
dawn_instance_.ProcessEvents();
}

if (!dawn_device_) {
if (!adapter_data.adapter) {
return amber::Result("could not find Vulkan or Metal backend for Dawn");
}

backendProcs.deviceSetUncapturedErrorCallback(dawn_device_.Get(),
PrintDeviceError, nullptr);
wgpu::DeviceDescriptor device_desc;
Comment thread
dj2 marked this conversation as resolved.
device_desc.nextInChain = &toggles;
device_desc.SetUncapturedErrorCallback(PrintDeviceError);
device_desc.SetDeviceLostCallback(wgpu::CallbackMode::AllowProcessEvents,
HandleDeviceLost);

// Use synchronous CreateDevice extension in Dawn
dawn_device_ = adapter_data.adapter.CreateDevice(&device_desc);

if (!dawn_device_) {
return amber::Result("could not create Dawn device");
}

auto* dawn_config = new amber::DawnEngineConfig;
dawn_config->device = &dawn_device_;
dawn_config->instance = dawn_instance_;
dawn_config->device = dawn_device_;
config->reset(dawn_config);

return {};
Expand Down
8 changes: 4 additions & 4 deletions samples/config_helper_dawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
#ifndef SAMPLES_CONFIG_HELPER_DAWN_H_
#define SAMPLES_CONFIG_HELPER_DAWN_H_

#include <webgpu/webgpu_cpp.h>

#include <limits>
#include <memory>
#include <string>
#include <vector>

#include "amber/amber.h"
#include "amber/amber_dawn.h"
#include "dawn_native/DawnNative.h"
#include "samples/config_helper.h"

namespace sample {
Expand All @@ -49,8 +49,8 @@ class ConfigHelperDawn : public ConfigHelperImpl {
std::unique_ptr<amber::EngineConfig>* config) override;

private:
::dawn_native::Instance dawn_instance_;
::dawn::Device dawn_device_;
wgpu::Instance dawn_instance_;
wgpu::Device dawn_device_;
};

} // namespace sample
Expand Down
2 changes: 1 addition & 1 deletion src/dawn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ amber_default_compile_options(libamberenginedawn)
set_target_properties(libamberenginedawn PROPERTIES
OUTPUT_NAME "amberenginedawn"
)
target_link_libraries(libamberenginedawn libamber Dawn::dawn_native Dawn::dawn)
target_link_libraries(libamberenginedawn libamber Dawn::dawn)
Loading