Split the libdawn target in components with a single purpose.

The functionality of the dawn_headers and libdawn targets are split into
the following targets:

 - dawn_headers: the new version only exposes the "dawn.h" C API and no
   longer includes the C++ API.
 - dawncpp: the header and implementation of the C++ API that wraps the
   C API. This is unbundled from the rest so the C++ API can be used
   with libdawn_proc or other libraries implementing the C API.
 - libdawn_proc: A DawnProcTable-backend implementation of the C API.

This is needed because in follow-up commit there will be three libraries
implementing the C API: libdawn_proc that trampolines where we want, and
libdawn_native/wire that don't have trampolines for better perf.

BUG=dawn:22

Change-Id: I5d941f0d98e5a4b633e14d67eb5269f7924f0647
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/12160
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2019-10-15 11:44:38 +00:00 committed by Commit Bot service account
parent 1093c4de2c
commit 96496828a0
22 changed files with 159 additions and 58 deletions

View File

@ -749,7 +749,8 @@ test("dawn_unittests") {
":libdawn_wire",
":mock_dawn_gen",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
"third_party:gmock_and_gtest",
]
@ -840,7 +841,8 @@ source_set("dawn_end2end_tests_sources") {
":libdawn_native",
":libdawn_wire",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
"third_party:gmock_and_gtest",
]
@ -917,7 +919,8 @@ source_set("dawn_white_box_tests_sources") {
":libdawn_native_sources",
":libdawn_wire",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
"third_party:gmock_and_gtest",
]
@ -950,7 +953,8 @@ test("dawn_end2end_tests") {
":libdawn_native",
":libdawn_wire",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
"third_party:gmock_and_gtest",
]
@ -982,7 +986,8 @@ test("dawn_perf_tests") {
":libdawn_native",
":libdawn_wire",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
"third_party:gmock_and_gtest",
]
@ -1059,7 +1064,8 @@ if (dawn_standalone) {
":libdawn_native",
":libdawn_wire",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
]
public_configs = [ "${dawn_root}/src/common:dawn_internal" ]
}

View File

@ -5,12 +5,16 @@ It exposes a C/C++ API that maps almost one-to-one to the WebGPU IDL and can be
Dawn provides several WebGPU building blocks:
- **WebGPU C/C++ headers** that applications and other building blocks use.
- The main C header for the WebGPU API.
- Definition of a structure of all function pointers for this specific Dawn version (called "proctable").
- A C++ wrapper for the C header.
- **A "native" implementation of WebGPU** using platforms' GPU APIs:
- **D3D12** on Windows 10
- **Metal** on OSX (and eventually iOS)
- **Vulkan** on Windows, Linux (eventually ChromeOS and Android too)
- **Vulkan** on Windows, Linux (eventually ChromeOS, Android and Fuchsia too)
- OpenGL as best effort where available
- **A client-server implementation of WebGPU** for applications that are in a sandbox without access to native drivers
- **A Dawn proc-table backend implementation of WebGPU** for applications what want to be able to switch at runtime between native or client-server mode.
## Directory structure

View File

@ -20,6 +20,7 @@
#include "utils/TerribleCommandBuffer.h"
#include <dawn/dawn.h>
#include <dawn/dawn_proc.h>
#include <dawn/dawn_wsi.h>
#include <dawn/dawncpp.h>
#include <dawn_native/DawnNative.h>
@ -160,7 +161,7 @@ dawn::Device CreateCppDawnDevice() {
break;
}
dawnSetProcs(&procs);
dawnProcSetProcs(&procs);
procs.deviceSetUncapturedErrorCallback(cDevice, PrintDeviceError, nullptr);
return dawn::Device::Acquire(cDevice);
}

View File

@ -453,7 +453,7 @@ class MultiGeneratorFromDawnJSON(Generator):
return 'Generates code for various target from Dawn.json.'
def add_commandline_arguments(self, parser):
allowed_targets = ['dawn_headers', 'libdawn', 'mock_dawn', 'dawn_wire', "dawn_native_utils"]
allowed_targets = ['dawn_headers', 'dawncpp', 'dawn_proc', 'mock_dawn', 'dawn_wire', "dawn_native_utils"]
parser.add_argument('--dawn-json', required=True, type=str, help ='The DAWN JSON definition to use.')
parser.add_argument('--wire-json', default=None, type=str, help='The DAWN WIRE JSON definition to use.')
@ -495,11 +495,13 @@ class MultiGeneratorFromDawnJSON(Generator):
if 'dawn_headers' in targets:
renders.append(FileRender('api.h', 'src/include/dawn/dawn.h', [base_params, api_params, c_params]))
renders.append(FileRender('apicpp.h', 'src/include/dawn/dawncpp.h', [base_params, api_params, cpp_params]))
renders.append(FileRender('api_proc_table.h', 'src/include/dawn/dawn_proc_table.h', [base_params, api_params, c_params]))
if 'libdawn' in targets:
additional_params = {'native_methods': lambda typ: cpp_native_methods(api_params['types'], typ)}
renders.append(FileRender('api.c', 'src/dawn/dawn.c', [base_params, api_params, c_params]))
if 'dawn_proc' in targets:
renders.append(FileRender('api_proc.c', 'src/dawn/dawn_proc.c', [base_params, api_params, c_params]))
if 'dawncpp' in targets:
renders.append(FileRender('apicpp.h', 'src/include/dawn/dawncpp.h', [base_params, api_params, cpp_params]))
renders.append(FileRender('apicpp.cpp', 'src/dawn/dawncpp.cpp', [base_params, api_params, cpp_params]))
if 'mock_dawn' in targets:

View File

@ -84,23 +84,8 @@ typedef void (*DawnFenceOnCompletionCallback)(DawnFenceCompletionStatus status,
{% endfor %}
#endif // !defined(DAWN_SKIP_PROCS)
struct DawnProcTable_s {
{% for type in by_category["object"] %}
{% for method in native_methods(type) %}
{{as_cProc(type.name, method.name)}} {{as_varName(type.name, method.name)}};
{% endfor %}
{% endfor %}
};
typedef struct DawnProcTable_s DawnProcTable;
// Stuff below is for convenience and will forward calls to a static DawnProcTable.
#if !defined(DAWN_SKIP_DECLARATIONS)
// Set which DawnProcTable will be used
DAWN_EXPORT void dawnSetProcs(const DawnProcTable* procs);
{% for type in by_category["object"] %}
// Methods of {{type.name.CamelCase()}}
{% for method in native_methods(type) %}

View File

@ -12,13 +12,13 @@
//* See the License for the specific language governing permissions and
//* limitations under the License.
#include "dawn/dawn.h"
#include "dawn/dawn_proc.h"
static DawnProcTable procs;
static DawnProcTable nullProcs;
void dawnSetProcs(const DawnProcTable* procs_) {
void dawnProcSetProcs(const DawnProcTable* procs_) {
if (procs_) {
procs = *procs_;
} else {

View File

@ -0,0 +1,29 @@
//* Copyright 2019 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.
#ifndef DAWN_DAWN_PROC_TABLE_H_
#define DAWN_DAWN_PROC_TABLE_H_
#include "dawn/dawn.h"
typedef struct DawnProcTable {
{% for type in by_category["object"] %}
{% for method in native_methods(type) %}
{{as_cProc(type.name, method.name)}} {{as_varName(type.name, method.name)}};
{% endfor %}
{% endfor %}
} DawnProcTable;
#endif // DAWN_DAWN_PROC_TABLE_H_

View File

@ -16,7 +16,6 @@
#define DAWN_DAWNCPP_H_
#include "dawn/dawn.h"
#include "dawn/dawn_export.h"
#include "dawn/EnumClassBitmasks.h"
namespace dawn {
@ -143,7 +142,7 @@ namespace dawn {
{% macro render_cpp_method_declaration(type, method) %}
{% set CppType = as_cppType(type.name) %}
DAWN_EXPORT {{as_cppType(method.return_type.name)}} {{method.name.CamelCase()}}(
{{as_cppType(method.return_type.name)}} {{method.name.CamelCase()}}(
{%- for arg in method.arguments -%}
{%- if not loop.first %}, {% endif -%}
{%- if arg.type.category == "object" and arg.annotation == "value" -%}
@ -170,8 +169,8 @@ namespace dawn {
private:
friend ObjectBase<{{CppType}}, {{CType}}>;
static DAWN_EXPORT void DawnReference({{CType}} handle);
static DAWN_EXPORT void DawnRelease({{CType}} handle);
static void DawnReference({{CType}} handle);
static void DawnRelease({{CType}} handle);
};
{% endfor %}

View File

@ -15,6 +15,7 @@
#ifndef DAWNWIRE_SERVER_SERVERBASE_H_
#define DAWNWIRE_SERVER_SERVERBASE_H_
#include "dawn/dawn_proc_table.h"
#include "dawn_wire/Wire.h"
#include "dawn_wire/WireCmd_autogen.h"
#include "dawn_wire/WireDeserializeAllocator.h"

View File

@ -15,8 +15,9 @@
#ifndef MOCK_DAWN_H
#define MOCK_DAWN_H
#include <gmock/gmock.h>
#include <dawn/dawn.h>
#include <dawn/dawn_proc_table.h>
#include <gmock/gmock.h>
#include <memory>

View File

@ -17,6 +17,14 @@ import("../../scripts/dawn_overrides_with_defaults.gni")
import("${dawn_root}/generator/dawn_generator.gni")
import("${dawn_root}/scripts/dawn_component.gni")
# Temporary group to not break Chromium `gn check` on Dawn CQ.
group("libdawn") {
deps = [
":dawncpp",
":libdawn_proc",
]
}
###############################################################################
# Dawn headers
###############################################################################
@ -24,46 +32,65 @@ import("${dawn_root}/scripts/dawn_component.gni")
dawn_json_generator("dawn_headers_gen") {
target = "dawn_headers"
outputs = [
"src/include/dawn/dawncpp.h",
"src/include/dawn/dawn.h",
"src/include/dawn/dawn_proc_table.h",
]
}
source_set("dawn_headers") {
all_dependent_configs = [ "${dawn_root}/src/common:dawn_public_include_dirs" ]
deps = [
public_deps = [
":dawn_headers_gen",
]
sources = get_target_outputs(":dawn_headers_gen")
sources += [
"${dawn_root}/src/include/dawn/EnumClassBitmasks.h",
"${dawn_root}/src/include/dawn/dawn_export.h",
"${dawn_root}/src/include/dawn/dawn_wsi.h",
]
}
###############################################################################
# libdawn
# Dawn C++ wrapper
###############################################################################
dawn_json_generator("libdawn_gen") {
target = "libdawn"
dawn_json_generator("dawncpp_gen") {
target = "dawncpp"
outputs = [
"src/dawn/dawncpp.cpp",
"src/dawn/dawn.c",
"src/include/dawn/dawncpp.h",
]
}
dawn_component("libdawn") {
source_set("dawncpp") {
deps = [
":dawn_headers",
":dawncpp_gen",
]
sources = get_target_outputs(":dawncpp_gen")
sources += [ "${dawn_root}/src/include/dawn/EnumClassBitmasks.h" ]
}
###############################################################################
# libdawn_proc
###############################################################################
dawn_json_generator("libdawn_proc_gen") {
target = "dawn_proc"
outputs = [
"src/dawn/dawn_proc.c",
]
}
dawn_component("libdawn_proc") {
DEFINE_PREFIX = "DAWN"
public_deps = [
":dawn_headers",
]
deps = [
":libdawn_gen",
":libdawn_proc_gen",
]
sources = get_target_outputs(":libdawn_gen")
sources = get_target_outputs(":libdawn_proc_gen")
sources += [ "${dawn_root}/src/include/dawn/dawn_proc.h" ]
}

View File

@ -12,8 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import("../../scripts/dawn_overrides_with_defaults.gni")
import("//build_overrides/build.gni")
import("../../scripts/dawn_overrides_with_defaults.gni")
# We only have libfuzzer in Chromium builds but if we build fuzzer targets only
# there, we would risk breaking fuzzer targets all the time when making changes
@ -127,7 +127,8 @@ dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") {
"${dawn_root}/:libdawn_native_static",
"${dawn_root}/:libdawn_wire_static",
"${dawn_root}/src/common",
"${dawn_root}/src/dawn:libdawn_static",
"${dawn_root}/src/dawn:dawncpp",
"${dawn_root}/src/dawn:libdawn_proc",
]
additional_configs = [ "${dawn_root}/src/common:dawn_internal" ]

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "common/Assert.h"
#include "dawn/dawn_proc.h"
#include "dawn/dawncpp.h"
#include "dawn_native/DawnNative.h"
#include "dawn_wire/WireServer.h"
@ -56,7 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
originalDeviceCreateSwapChain = procs.deviceCreateSwapChain;
procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain;
dawnSetProcs(&procs);
dawnProcSetProcs(&procs);
// Create an instance and find the null adapter to create a device with.
std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();

View File

@ -0,0 +1,36 @@
// Copyright 2019 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.
#ifndef DAWN_DAWN_PROC_H_
#define DAWN_DAWN_PROC_H_
#include "dawn/dawn.h"
#include "dawn/dawn_proc_table.h"
#ifdef __cplusplus
extern "C" {
#endif
// Sets the static proctable used by libdawn_proc to implement the Dawn entrypoints. Passing NULL
// for `procs` sets up the null proctable that contains only null function pointers. It is the
// default value of the proctable. Setting the proctable back to null is good practice when you
// are done using libdawn_proc since further usage will cause a segfault instead of calling an
// unexpected function.
DAWN_EXPORT void dawnProcSetProcs(const DawnProcTable* procs);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // DAWN_DAWN_PROC_H_

View File

@ -16,6 +16,7 @@
#define DAWNNATIVE_DAWNNATIVE_H_
#include <dawn/dawn.h>
#include <dawn/dawn_proc_table.h>
#include <dawn_native/dawn_native_export.h>
#include <string>

View File

@ -15,10 +15,11 @@
#ifndef DAWNWIRE_WIRECLIENT_H_
#define DAWNWIRE_WIRECLIENT_H_
#include <memory>
#include "dawn/dawn_proc_table.h"
#include "dawn_wire/Wire.h"
#include <memory>
namespace dawn_wire {
namespace client {

View File

@ -19,6 +19,8 @@
#include "dawn_wire/Wire.h"
struct DawnProcTable;
namespace dawn_wire {
namespace server {

View File

@ -18,6 +18,7 @@
#include "common/Constants.h"
#include "common/Math.h"
#include "common/Platform.h"
#include "dawn/dawn_proc.h"
#include "dawn_native/DawnNative.h"
#include "dawn_wire/WireClient.h"
#include "dawn_wire/WireServer.h"
@ -262,7 +263,7 @@ DawnTestBase::~DawnTestBase() {
backendProcs.deviceRelease(backendDevice);
}
dawnSetProcs(nullptr);
dawnProcSetProcs(nullptr);
}
bool DawnTestBase::IsD3D12() const {
@ -452,7 +453,7 @@ void DawnTestBase::SetUp() {
// Set up the device and queue because all tests need them, and DawnTestBase needs them too for
// the deferred expectations.
dawnSetProcs(&procs);
dawnProcSetProcs(&procs);
device = dawn::Device::Acquire(cDevice);
queue = device.CreateQueue();

View File

@ -15,6 +15,7 @@
#ifndef TESTS_DAWNTEST_H_
#define TESTS_DAWNTEST_H_
#include "dawn/dawn_proc_table.h"
#include "dawn/dawncpp.h"
#include "dawn_native/DawnNative.h"

View File

@ -16,6 +16,7 @@
#include "common/Assert.h"
#include "dawn/dawn.h"
#include "dawn/dawn_proc.h"
#include "dawn_native/NullBackend.h"
ValidationTest::ValidationTest() {
@ -37,7 +38,7 @@ ValidationTest::ValidationTest() {
ASSERT(foundNullAdapter);
DawnProcTable procs = dawn_native::GetProcs();
dawnSetProcs(&procs);
dawnProcSetProcs(&procs);
device = CreateDeviceFromAdapter(adapter, std::vector<const char*>());
}
@ -64,7 +65,7 @@ ValidationTest::~ValidationTest() {
// We need to destroy Dawn objects before setting the procs to null otherwise the dawn*Release
// will call a nullptr
device = dawn::Device();
dawnSetProcs(nullptr);
dawnProcSetProcs(nullptr);
}
void ValidationTest::TearDown() {

View File

@ -14,6 +14,7 @@
#include "tests/unittests/wire/WireTest.h"
#include "dawn/dawn_proc.h"
#include "dawn_wire/WireClient.h"
#include "dawn_wire/WireServer.h"
#include "utils/TerribleCommandBuffer.h"
@ -65,13 +66,13 @@ void WireTest::SetUp() {
device = mWireClient->GetDevice();
DawnProcTable clientProcs = mWireClient->GetProcs();
dawnSetProcs(&clientProcs);
dawnProcSetProcs(&clientProcs);
apiDevice = mockDevice;
}
void WireTest::TearDown() {
dawnSetProcs(nullptr);
dawnProcSetProcs(nullptr);
// Derived classes should call the base TearDown() first. The client must
// be reset before any mocks are deleted.

View File

@ -15,7 +15,7 @@
#ifndef UTILS_BACKENDBINDING_H_
#define UTILS_BACKENDBINDING_H_
#include "dawn/dawncpp.h"
#include "dawn/dawn.h"
#include "dawn_native/DawnNative.h"
struct GLFWwindow;