Merge upstream & update dependencies

This commit is contained in:
Luke Street 2023-05-27 11:38:11 -04:00
commit 0bd776df12
37232 changed files with 1278304 additions and 430258 deletions

1
.gitattributes vendored
View File

@ -9,3 +9,4 @@
*.wgsl eol=lf
*.h eol=lf
*.cpp eol=lf
*.bat eol=crlf

9
.gitignore vendored
View File

@ -4,17 +4,20 @@
/.cipd
/.gclient
/.gclient_entries
/.gclient_previous_custom_vars
/.gclient_previous_sync_commits
/build
/buildtools
/testing
/tools/bin
/tools/clang
/tools/cmake*
/tools/golang
/tools/memory
/out
# Tint test validation cache file
/test/tint/validation.cache
# Modified from https://www.gitignore.io/api/vim,macos,linux,emacs,windows,sublimetext,visualstudio,visualstudiocode,intellij
### Emacs ###
@ -86,9 +89,6 @@ $RECYCLE.BIN/
### Intellij ###
.idea
### Dawn node tools binaries
src/dawn/node/tools/bin/
### Cached node transpiled tools
/.node_transpile_work_dir
@ -104,3 +104,4 @@ lcov.info
### Clang-Tidy files
all_findings.json
tint.dot

95
.vscode/tasks.json vendored
View File

@ -73,66 +73,14 @@
// A symbolic link to this build directory is created at 'out/active'
// which is used to track the active build directory.
{
"label": "gn gen",
"label": "setup build",
"type": "shell",
"linux": {
"command": "./tools/setup-build",
"args": [
"gn",
"${input:buildType}",
],
},
"osx": {
"command": "./tools/setup-build",
"args": [
"gn",
"${input:buildType}",
],
},
"windows": {
"command": "/C",
"args": [
"(IF \"${input:buildType}\" == \"Debug\" ( gn gen \"out\\${input:buildType}\" --args=is_debug=true ) ELSE ( gn gen \"out\\${input:buildType}\" --args=is_debug=false )) && (IF EXIST \"out\\active\" rmdir \"out\\active\" /q /s) && (mklink /j \"out\\active\" \"out\\${input:buildType}\")",
],
"options": {
"shell": {
"executable": "cmd"
},
}
},
"options": {
"cwd": "${workspaceRoot}"
},
"problemMatcher": [],
},
{
"label": "cmake gen",
"type": "shell",
"linux": {
"command": "./tools/setup-build",
"args": [
"cmake",
"${input:buildType}",
],
},
"osx": {
"command": "./tools/setup-build",
"args": [
"cmake",
"${input:buildType}",
],
},
"windows": {
"command": "/C",
"args": [
"echo TODO",
],
"options": {
"shell": {
"executable": "cmd"
},
}
},
"command": "./tools/setup-build",
"args": [
"${input:buildSystem}",
"${input:buildType}",
"${input:buildArch}",
],
"options": {
"cwd": "${workspaceRoot}"
},
@ -177,19 +125,24 @@
{
"label": "push",
"type": "shell",
"command": "git",
"args": [
"push",
"origin",
"HEAD:refs/for/main"
],
"command": "./tools/push-to-gerrit",
"options": {
"cwd": "${workspaceRoot}"
},
"problemMatcher": [],
}
},
],
"inputs": [
{
"id": "buildSystem",
"type": "pickString",
"options": [
"cmake",
"gn",
],
"default": "gn",
"description": "The build system",
},
{
"id": "buildType",
"type": "pickString",
@ -200,5 +153,15 @@
"default": "Debug",
"description": "The type of build",
},
{
"id": "buildArch",
"type": "pickString",
"options": [
"native",
"x86",
],
"default": "native",
"description": "The build architecture",
},
]
}

View File

@ -77,6 +77,7 @@ function (set_if_not_defined name value description)
endfunction()
# Default values for the backend-enabling options
set(ENABLE_D3D11 OFF)
set(ENABLE_D3D12 OFF)
set(ENABLE_METAL OFF)
set(ENABLE_OPENGLES OFF)
@ -86,6 +87,7 @@ set(USE_WAYLAND OFF)
set(USE_X11 OFF)
set(BUILD_SAMPLES OFF)
if (WIN32)
set(ENABLE_D3D11 ON)
set(ENABLE_D3D12 ON)
if (NOT WINDOWS_STORE)
# Enable Vulkan in win32 compilation only
@ -119,6 +121,7 @@ option_if_not_defined(DAWN_ENABLE_TSAN "Enable thread sanitizer" OFF)
option_if_not_defined(DAWN_ENABLE_MSAN "Enable memory sanitizer" OFF)
option_if_not_defined(DAWN_ENABLE_UBSAN "Enable undefined behaviour sanitizer" OFF)
option_if_not_defined(DAWN_ENABLE_D3D11 "Enable compilation of the D3D11 backend" ${ENABLE_D3D11})
option_if_not_defined(DAWN_ENABLE_D3D12 "Enable compilation of the D3D12 backend" ${ENABLE_D3D12})
option_if_not_defined(DAWN_ENABLE_METAL "Enable compilation of the Metal backend" ${ENABLE_METAL})
option_if_not_defined(DAWN_ENABLE_NULL "Enable compilation of the Null backend" ON)
@ -133,9 +136,13 @@ option_if_not_defined(DAWN_USE_X11 "Enable support for X11 surface" ${USE_X11})
option_if_not_defined(DAWN_BUILD_SAMPLES "Enables building Dawn's samples" ${BUILD_SAMPLES})
option_if_not_defined(DAWN_BUILD_NODE_BINDINGS "Enables building Dawn's NodeJS bindings" OFF)
option_if_not_defined(DAWN_ENABLE_SWIFTSHADER "Enables building Swiftshader as part of the build and Vulkan adapter discovery" OFF)
option_if_not_defined(DAWN_BUILD_BENCHMARKS "Build Dawn benchmarks" OFF)
option_if_not_defined(DAWN_ENABLE_PIC "Build with Position-Independent-Code enabled" OFF)
option_if_not_defined(DAWN_EMIT_COVERAGE "Emit code coverage information" OFF)
set_if_not_defined(LLVM_SOURCE_DIR "${Dawn_LLVM_SOURCE_DIR}" "Directory to an LLVM source checkout. Required to build turbo-cov")
if (DAWN_ENABLE_OPENGLES OR DAWN_ENABLE_DESKTOP_GL)
set(TINT_DEFAULT_GLSL ON)
else()
@ -154,33 +161,39 @@ option_if_not_defined(TINT_BUILD_MSL_WRITER "Build the MSL output writer" ${DAWN
option_if_not_defined(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ${DAWN_ENABLE_VULKAN})
option_if_not_defined(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
option_if_not_defined(TINT_BUILD_SYNTAX_TREE_WRITER "Build the syntax tree writer" OFF)
option_if_not_defined(TINT_BUILD_IR "Build the IR" ON)
option_if_not_defined(TINT_BUILD_FUZZERS "Build fuzzers" OFF)
option_if_not_defined(TINT_BUILD_SPIRV_TOOLS_FUZZER "Build SPIRV-Tools fuzzer" OFF)
option_if_not_defined(TINT_BUILD_AST_FUZZER "Build AST fuzzer" OFF)
option_if_not_defined(TINT_BUILD_REGEX_FUZZER "Build regex fuzzer" OFF)
option_if_not_defined(TINT_BUILD_BENCHMARKS "Build benchmarks" OFF)
option_if_not_defined(TINT_BUILD_BENCHMARKS "Build Tint benchmarks" OFF)
option_if_not_defined(TINT_BUILD_TESTS "Build tests" OFF)
option_if_not_defined(TINT_BUILD_AS_OTHER_OS "Override OS detection to force building of *_other.cc files" OFF)
option_if_not_defined(TINT_BUILD_REMOTE_COMPILE "Build the remote-compile tool for validating shaders on a remote machine" OFF)
set_if_not_defined(TINT_EXTERNAL_BENCHMARK_CORPUS_DIR "" "Directory that holds a corpus of external shaders to benchmark.")
option_if_not_defined(TINT_ENABLE_BREAK_IN_DEBUGGER "Enable tint::debugger::Break()" OFF)
option_if_not_defined(TINT_EMIT_COVERAGE "Emit code coverage information" OFF)
option_if_not_defined(TINT_CHECK_CHROMIUM_STYLE "Check for [chromium-style] issues during build" OFF)
option_if_not_defined(TINT_SYMBOL_STORE_DEBUG_NAME "Enable storing of name in tint::ast::Symbol to help debugging the AST" OFF)
option_if_not_defined(TINT_RANDOMIZE_HASHES "Randomize the hash seed value to detect non-deterministic output" OFF)
# Recommended setting for compability with future abseil releases.
set(ABSL_PROPAGATE_CXX_STD ON)
set_if_not_defined(DAWN_THIRD_PARTY_DIR "${Dawn_SOURCE_DIR}/third_party" "Directory in which to find third-party dependencies.")
set_if_not_defined(DAWN_VULKAN_DEPS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps" "Directory in which to find vulkan-deps")
set_if_not_defined(DAWN_ABSEIL_DIR "${DAWN_THIRD_PARTY_DIR}/abseil-cpp" "Directory in which to find Abseil")
set_if_not_defined(DAWN_GLFW_DIR "${DAWN_THIRD_PARTY_DIR}/glfw" "Directory in which to find GLFW")
set_if_not_defined(DAWN_JINJA2_DIR "${DAWN_THIRD_PARTY_DIR}/jinja2" "Directory in which to find Jinja2")
set_if_not_defined(DAWN_MARKUPSAFE_DIR "${DAWN_THIRD_PARTY_DIR}/markupsafe" "Directory in which to find MarkupSafe")
set_if_not_defined(DAWN_KHRONOS_DIR "${DAWN_THIRD_PARTY_DIR}/khronos" "Directory in which to find Khronos GL headers")
set_if_not_defined(DAWN_SPIRV_HEADERS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/spirv-headers/src" "Directory in which to find SPIRV-Headers")
set_if_not_defined(DAWN_SPIRV_TOOLS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps/spirv-tools/src" "Directory in which to find SPIRV-Tools")
set_if_not_defined(DAWN_SWIFTSHADER_DIR "${DAWN_THIRD_PARTY_DIR}/swiftshader" "Directory in which to find swiftshader")
set_if_not_defined(DAWN_TINT_DIR "${Dawn_SOURCE_DIR}" "Directory in which to find Tint")
set_if_not_defined(DAWN_VULKAN_DEPS_DIR "${DAWN_THIRD_PARTY_DIR}/vulkan-deps" "Directory in which to find vulkan-deps")
set_if_not_defined(DAWN_SPIRV_TOOLS_DIR "${DAWN_VULKAN_DEPS_DIR}/spirv-tools/src" "Directory in which to find SPIRV-Tools")
set_if_not_defined(DAWN_SPIRV_HEADERS_DIR "${DAWN_VULKAN_DEPS_DIR}/spirv-headers/src" "Directory in which to find SPIRV-Headers")
set_if_not_defined(DAWN_VULKAN_HEADERS_DIR "${DAWN_VULKAN_DEPS_DIR}/vulkan-headers/src" "Directory in which to find Vulkan-Headers")
set_if_not_defined(DAWN_VULKAN_TOOLS_DIR "${DAWN_VULKAN_DEPS_DIR}/vulkan-tools/src" "Directory in which to find Vulkan-Tools")
@ -190,6 +203,8 @@ set_if_not_defined(NODE_API_HEADERS_DIR "${DAWN_THIRD_PARTY_DIR}/node-api-header
set_if_not_defined(WEBGPU_IDL_PATH "${DAWN_THIRD_PARTY_DIR}/gpuweb/webgpu.idl" "Path to the webgpu.idl definition file")
set_if_not_defined(GO_EXECUTABLE "go" "Golang executable for running the IDL generator")
option_if_not_defined(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" OFF)
# Much of the backend code is shared among desktop OpenGL and OpenGL ES
if (${DAWN_ENABLE_DESKTOP_GL} OR ${DAWN_ENABLE_OPENGLES})
set(DAWN_ENABLE_OPENGL ON)
@ -255,6 +270,7 @@ if (${TINT_BUILD_REGEX_FUZZER})
set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "Build HLSL writer" FORCE)
endif()
message(STATUS "Dawn build D3D11 backend: ${DAWN_ENABLE_D3D11}")
message(STATUS "Dawn build D3D12 backend: ${DAWN_ENABLE_D3D12}")
message(STATUS "Dawn build Metal backend: ${DAWN_ENABLE_METAL}")
message(STATUS "Dawn build Vulkan backend: ${DAWN_ENABLE_VULKAN}")
@ -269,6 +285,7 @@ message(STATUS "Dawn build X11 support: ${DAWN_USE_X11}")
message(STATUS "Dawn build samples: ${DAWN_BUILD_SAMPLES}")
message(STATUS "Dawn build Node bindings: ${DAWN_BUILD_NODE_BINDINGS}")
message(STATUS "Dawn build Swiftshader: ${DAWN_ENABLE_SWIFTSHADER}")
message(STATUS "Dawn build benchmarks: ${DAWN_BUILD_BENCHMARKS}")
message(STATUS "Dawn build PIC: ${DAWN_ENABLE_PIC}")
@ -287,6 +304,8 @@ message(STATUS "Tint build HLSL writer: ${TINT_BUILD_HLSL_WRITER}")
message(STATUS "Tint build MSL writer: ${TINT_BUILD_MSL_WRITER}")
message(STATUS "Tint build SPIR-V writer: ${TINT_BUILD_SPV_WRITER}")
message(STATUS "Tint build WGSL writer: ${TINT_BUILD_WGSL_WRITER}")
message(STATUS "Tint build Syntax Tree writer: ${TINT_BUILD_SYNTAX_TREE_WRITER}")
message(STATUS "Tint build IR: ${TINT_BUILD_IR}")
message(STATUS "Tint build fuzzers: ${TINT_BUILD_FUZZERS}")
message(STATUS "Tint build SPIRV-Tools fuzzer: ${TINT_BUILD_SPIRV_TOOLS_FUZZER}")
message(STATUS "Tint build AST fuzzer: ${TINT_BUILD_AST_FUZZER}")
@ -295,6 +314,8 @@ message(STATUS "Tint build benchmarks: ${TINT_BUILD_BENCHMARKS}")
message(STATUS "Tint build tests: ${TINT_BUILD_TESTS}")
message(STATUS "Tint build checking [chromium-style]: ${TINT_CHECK_CHROMIUM_STYLE}")
message(STATUS "Tint build remote-compile tool: ${TINT_BUILD_REMOTE_COMPILE}")
message(STATUS "Tint external benchmark corpus dir: ${TINT_EXTERNAL_BENCHMARK_CORPUS_DIR}")
if (NOT ${TINT_LIB_FUZZING_ENGINE_LINK_OPTIONS} STREQUAL "")
message(STATUS "Using provided LIB_FUZZING_ENGINE options: ${TINT_LIB_FUZZING_ENGINE_LINK_OPTIONS}")
@ -303,7 +324,6 @@ endif()
message(STATUS "Using python3")
find_package(PythonInterp 3 REQUIRED)
################################################################################
# common_compile_options - sets compiler and linker options common for dawn and
# tint on the given target
@ -313,7 +333,9 @@ function(common_compile_options TARGET)
target_compile_options(${TARGET} PRIVATE
-fno-exceptions
-fno-rtti
-fvisibility-inlines-hidden
-Wno-deprecated-builtins
-Wno-unknown-warning-option
)
if (${DAWN_ENABLE_MSAN})
@ -326,10 +348,27 @@ function(common_compile_options TARGET)
target_compile_options(${TARGET} PUBLIC -fsanitize=thread)
target_link_options(${TARGET} PUBLIC -fsanitize=thread)
elseif (${DAWN_ENABLE_UBSAN})
target_compile_options(${TARGET} PUBLIC -fsanitize=undefined)
target_link_options(${TARGET} PUBLIC -fsanitize=undefined)
target_compile_options(${TARGET} PUBLIC -fsanitize=undefined -fsanitize=float-divide-by-zero)
target_link_options(${TARGET} PUBLIC -fsanitize=undefined -fsanitize=float-divide-by-zero)
endif()
endif(COMPILER_IS_LIKE_GNU)
if(MSVC)
target_compile_options(${TARGET} PUBLIC /utf-8)
endif()
if (DAWN_EMIT_COVERAGE)
target_compile_definitions(${TARGET} PRIVATE "DAWN_EMIT_COVERAGE")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
target_compile_options(${TARGET} PRIVATE "--coverage")
target_link_options(${TARGET} PRIVATE "gcov")
elseif(COMPILER_IS_CLANG OR COMPILER_IS_CLANG_CL)
target_compile_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
target_link_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
else()
message(FATAL_ERROR "Coverage generation not supported for the ${CMAKE_CXX_COMPILER_ID} toolchain")
endif()
endif(DAWN_EMIT_COVERAGE)
endfunction()
if (${DAWN_ENABLE_TSAN})
@ -341,6 +380,12 @@ endif()
# Dawn's public and internal "configs"
################################################################################
set(IS_DEBUG_BUILD 0)
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
if ((NOT ${build_type} STREQUAL "RELEASE") AND (NOT ${build_type} STREQUAL "RELWITHDEBINFO"))
set(IS_DEBUG_BUILD 1)
endif()
# The public config contains only the include paths for the Dawn headers.
add_library(dawn_public_config INTERFACE)
target_include_directories(dawn_public_config INTERFACE
@ -357,9 +402,12 @@ target_include_directories(dawn_internal_config INTERFACE
target_link_libraries(dawn_internal_config INTERFACE dawn_public_config)
# Compile definitions for the internal config
if (DAWN_ALWAYS_ASSERT OR CMAKE_BUILD_TYPE STREQUAL Debug)
if (DAWN_ALWAYS_ASSERT OR IS_DEBUG_BUILD)
target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_ASSERTS")
endif()
if (DAWN_ENABLE_D3D11)
target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_D3D11")
endif()
if (DAWN_ENABLE_D3D12)
target_compile_definitions(dawn_internal_config INTERFACE "DAWN_ENABLE_BACKEND_D3D12")
endif()
@ -421,10 +469,13 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_SIMULATE_ID STREQUAL
set(COMPILER_IS_CLANG_CL TRUE)
endif()
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
if((CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND
(NOT COMPILER_IS_CLANG_CL)))
set(COMPILER_IS_CLANG TRUE)
endif()
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR COMPILER_IS_CLANG)
set(COMPILER_IS_LIKE_GNU TRUE)
endif()
@ -488,20 +539,11 @@ function(tint_core_compile_options TARGET)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_MSL_WRITER=$<BOOL:${TINT_BUILD_MSL_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_SPV_WRITER=$<BOOL:${TINT_BUILD_SPV_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_WGSL_WRITER=$<BOOL:${TINT_BUILD_WGSL_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC
-DTINT_BUILD_SYNTAX_TREE_WRITER=$<BOOL:${TINT_BUILD_SYNTAX_TREE_WRITER}>)
target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_IR=$<BOOL:${TINT_BUILD_IR}>)
common_compile_options(${TARGET})
if (TINT_EMIT_COVERAGE)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
target_compile_options(${TARGET} PRIVATE "--coverage")
target_link_options(${TARGET} PRIVATE "gcov")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
target_link_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
else()
message(FATAL_ERROR "Coverage generation not supported for the ${CMAKE_CXX_COMPILER_ID} toolchain")
endif()
endif(TINT_EMIT_COVERAGE)
endfunction()
function(tint_default_compile_options TARGET)
@ -521,9 +563,11 @@ function(tint_default_compile_options TARGET)
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-format-pedantic
-Wno-poison-system-directories
-Wno-return-std-move-in-c++11
-Wno-unknown-warning-option
-Wno-undefined-var-template
-Wno-unsafe-buffer-usage
-Wno-used-but-marked-unused
-Weverything
)
@ -534,8 +578,7 @@ function(tint_default_compile_options TARGET)
${COMMON_GNU_OPTIONS}
)
if (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") OR
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang"))
if (COMPILER_IS_CLANG)
target_compile_options(${TARGET} PRIVATE
${COMMON_CLANG_OPTIONS}
)
@ -583,6 +626,15 @@ function(tint_default_compile_options TARGET)
)
endif()
endif()
if (TINT_RANDOMIZE_HASHES)
if(NOT DEFINED TINT_HASH_SEED)
string(RANDOM LENGTH 16 ALPHABET "0123456789abcdef" seed)
set(TINT_HASH_SEED "0x${seed}" CACHE STRING "Tint hash seed value")
message("Using TINT_HASH_SEED: ${TINT_HASH_SEED}")
endif()
target_compile_definitions(${TARGET} PUBLIC "-DTINT_HASH_SEED=${TINT_HASH_SEED}")
endif()
endfunction()
################################################################################
@ -625,9 +677,11 @@ add_custom_target(tint-format
COMMENT "Running formatter"
VERBATIM)
if (DAWN_EMIT_COVERAGE)
add_subdirectory(tools/src/cmd/turbo-cov)
if (TINT_EMIT_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Generates a lcov.info file at the project root.
# The tint-generate-coverage target generates a lcov.info file at the project
# root, holding the code coverage for all the tint_unitests.
# This can be used by tools such as VSCode's Coverage Gutters extension to
# visualize code coverage in the editor.
get_filename_component(CLANG_BIN_DIR ${CMAKE_C_COMPILER} DIRECTORY)

73
DEPS
View File

@ -17,6 +17,9 @@ vars = {
'dawn_cmake_version': 'version:2@3.23.3',
'dawn_cmake_win32_sha1': 'b106d66bcdc8a71ea2cdf5446091327bfdb1bcd7',
'dawn_gn_version': 'git_revision:bd99dbf98cbdefe18a4128189665c5761263bcfb',
# ninja CIPD package version.
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
'dawn_ninja_version': 'version:2@1.11.1.chromium.6',
'dawn_go_version': 'version:2@1.18.4',
'node_darwin_arm64_sha': '31859fc1fa0994a95f44f09c367d6ff63607cfde',
@ -34,14 +37,14 @@ vars = {
deps = {
# Dependencies required to use GN/Clang in standalone
'build': {
'url': '{chromium_git}/chromium/src/build@f14f6d206b9a0c81a0fefba487bcba0d90ddb5fe',
'url': '{chromium_git}/chromium/src/build@1103ef535ca1e100db5d4e59781a4e59369a9818',
'condition': 'dawn_standalone',
},
'buildtools': {
'url': '{chromium_git}/chromium/src/buildtools@fe57e98eeb2172d7517f6dec1072ca641a019893',
'url': '{chromium_git}/chromium/src/buildtools@2ff42d2008f09f65de12e70c6ff0ad58ddb090ad',
'condition': 'dawn_standalone',
},
'buildtools/clang_format/script': {
'third_party/clang-format/script': {
'url': '{chromium_git}/external/github.com/llvm/llvm-project/clang/tools/clang-format.git@8b525d2747f2584fc35d8c7e612e66f377858df7',
'condition': 'dawn_standalone',
},
@ -71,17 +74,17 @@ deps = {
},
'buildtools/third_party/libc++/trunk': {
'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxx.git@eb79671bfbedd77b747d01dee8c0479ff1693f88',
'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxx.git@c1341b9a1a7de7c193a23bf003d5479c48957f7d',
'condition': 'dawn_standalone',
},
'buildtools/third_party/libc++abi/trunk': {
'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxxabi.git@b954e3e65634a9e2f7b595598a30c455f5f2eb26',
'url': '{chromium_git}/external/github.com/llvm/llvm-project/libcxxabi.git@f7460fc60ab56553f0b3b0853f1ea60aa51b9478',
'condition': 'dawn_standalone',
},
'tools/clang': {
'url': '{chromium_git}/chromium/src/tools/clang@3d8d88e8bb600789ba3e798f38ff314521aac524',
'url': '{chromium_git}/chromium/src/tools/clang@effd9257d456f2d42e9e22fa4f37a24d8cf0b5b5',
'condition': 'dawn_standalone',
},
'tools/clang/dsymutil': {
@ -95,16 +98,20 @@ deps = {
# Testing, GTest and GMock
'testing': {
'url': '{chromium_git}/chromium/src/testing@1f497ac0b0afc242222780a4789d13fbf00073eb',
'url': '{chromium_git}/chromium/src/testing@166db27fd0d53afc0c716b1ae9c15725e380871f',
'condition': 'dawn_standalone',
},
'third_party/googletest': {
'url': '{chromium_git}/external/github.com/google/googletest@bda85449f48f2d80a494c8c07766b6aba3170f3b',
'url': '{chromium_git}/external/github.com/google/googletest@7a7231c442484be389fdf01594310349ca0e42a8',
'condition': 'dawn_standalone',
},
# This is a dependency of //testing
'third_party/catapult': {
'url': '{chromium_git}/catapult.git@fa35beefb3429605035f98211ddb8750dee6a13d',
'url': '{chromium_git}/catapult.git@c1e70d412ce01fb194f73f7abfdac710aae87dae',
'condition': 'dawn_standalone',
},
'third_party/google_benchmark/src': {
'url': '{chromium_git}/external/github.com/google/benchmark.git' + '@' + 'efc89f0b524780b1994d5dddd83a92718e5be492',
'condition': 'dawn_standalone',
},
@ -129,17 +136,17 @@ deps = {
},
'third_party/angle': {
'url': '{chromium_git}/angle/angle@5ef3960bc1f10d180331a8134b0d11139fa1f913',
'url': '{chromium_git}/angle/angle@ff110417bb04e9bc13079eeed99940009d9c3ce1',
'condition': 'dawn_standalone',
},
'third_party/swiftshader': {
'url': '{swiftshader_git}/SwiftShader@476165cc7c0c7247869c13f7f80dd25ec1fd2b03',
'url': '{swiftshader_git}/SwiftShader@f549d5e6c6635ec8b75fb544a6bdc9f48bfb1dd3',
'condition': 'dawn_standalone',
},
'third_party/vulkan-deps': {
'url': '{chromium_git}/vulkan-deps@c5f01bfc31ec5b7165eebf9f241890744edc7789',
'url': '{chromium_git}/vulkan-deps@25c584aa4cec2d79706854dafbd52392389d8004',
'condition': 'dawn_standalone',
},
@ -155,7 +162,7 @@ deps = {
# WebGPU CTS - not used directly by Dawn, only transitively by Chromium.
'third_party/webgpu-cts': {
'url': '{chromium_git}/external/github.com/gpuweb/cts@27dc745ca167d1e9eb956947f2109441dca0b4f7',
'url': '{chromium_git}/external/github.com/gpuweb/cts@b033a4f1ae4a0e19ae4d5563fae023001bbf570f',
'condition': 'build_with_chromium',
},
@ -169,12 +176,11 @@ deps = {
'condition': 'dawn_node',
},
'third_party/gpuweb': {
'url': '{github_git}/gpuweb/gpuweb.git@3c4734b09c68eb800b15da5e9ecefeca735fa7df',
'url': '{github_git}/gpuweb/gpuweb.git@2e75d5e68e80e4c28575c7836ee00ca22cf4ca63',
'condition': 'dawn_node',
},
'tools/golang': {
'condition': 'dawn_node',
'packages': [{
'package': 'infra/3pp/tools/go/${{platform}}',
'version': Var('dawn_go_version'),
@ -191,11 +197,17 @@ deps = {
'dep_type': 'cipd',
},
# Misc dependencies inherited from Tint
'third_party/benchmark': {
'url': '{chromium_git}/external/github.com/google/benchmark.git@e991355c02b93fe17713efe04cbc2e278e00fdbd',
'condition': 'dawn_standalone',
'third_party/ninja': {
'packages': [
{
'package': 'infra/3pp/tools/ninja/${{platform}}',
'version': Var('dawn_ninja_version'),
}
],
'dep_type': 'cipd',
},
# Misc dependencies inherited from Tint
'third_party/protobuf': {
'url': '{chromium_git}/external/github.com/protocolbuffers/protobuf.git@fde7cf7358ec7cd69e8db9be4f1fa6a5c431386a',
'condition': 'dawn_standalone',
@ -226,6 +238,18 @@ hooks = [
'condition': 'dawn_standalone and checkout_mac',
'action': ['python3', 'build/mac_toolchain.py'],
},
{
# Case-insensitivity for the Win SDK. Must run before win_toolchain below.
'name': 'ciopfs_linux',
'pattern': '.',
'condition': 'dawn_standalone and checkout_win and host_os == "linux"',
'action': [ 'download_from_google_storage',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/ciopfs',
'-s', 'build/ciopfs.sha1',
]
},
{
# Update the Windows toolchain if necessary. Must run before 'clang' below.
'name': 'win_toolchain',
@ -261,6 +285,17 @@ hooks = [
'-s', 'build/toolchain/win/rc/win/rc.exe.sha1',
],
},
{
'name': 'rc_linux',
'pattern': '.',
'condition': 'dawn_standalone and checkout_win and host_os == "linux"',
'action': [ 'download_from_google_storage',
'--no_resume',
'--no_auth',
'--bucket', 'chromium-browser-clang/rc',
'-s', 'build/toolchain/win/rc/linux64/rc.sha1',
]
},
# Pull clang-format binaries using checked-in hashes.
{
'name': 'clang_format_win',

753
Doxyfile

File diff suppressed because it is too large Load Diff

3
OWNERS
View File

@ -7,7 +7,8 @@ dsinclair@chromium.org
enga@chromium.org
jiawei.shao@intel.com
# TODO(dawn:1337): Move this file in src/dawn.
# TODO(crbug.com/dawn/1339): Move dawn.json into src/dawn.
per-file dawn.json=file://src/dawn/OWNERS
per-file DEPS=*
per-file README.md=file://docs/OWNERS

View File

@ -114,7 +114,7 @@ def _NonInclusiveFileFilter(file):
"src/dawn/native/metal/BackendMTL.mm", # OSX Constant
"src/dawn/native/vulkan/SamplerVk.cpp", # External URL
"src/dawn/native/vulkan/TextureVk.cpp", # External URL
"src/dawn/node/tools/src/cmd/run-cts/main.go", # Terminal type name
"src/tools/src/cmd/run-cts/main.go", # Terminal type name
"src/dawn/samples/ComputeBoids.cpp", # External URL
"src/dawn/tests/end2end/DepthBiasTests.cpp", # External URL
"src/tint/transform/canonicalize_entry_point_io.cc", # External URL
@ -127,14 +127,42 @@ def _NonInclusiveFileFilter(file):
return file.LocalPath() not in filter_list
def _CheckNoStaleGen(input_api, output_api):
results = []
try:
go = input_api.os_path.join(input_api.change.RepositoryRoot(), "tools",
"golang", "bin", "go")
if input_api.is_windows:
go += '.exe'
input_api.subprocess.check_call_out(
[go, "run", "tools/src/cmd/gen/main.go", "--check-stale"],
stdout=input_api.subprocess.PIPE,
stderr=input_api.subprocess.PIPE,
cwd=input_api.change.RepositoryRoot())
except input_api.subprocess.CalledProcessError as e:
if input_api.is_committing:
results.append(output_api.PresubmitError('%s' % (e, )))
else:
results.append(output_api.PresubmitPromptWarning('%s' % (e, )))
return results
def _DoCommonChecks(input_api, output_api):
results = []
results.extend(_CheckNoStaleGen(input_api, output_api))
results.extend(
input_api.canned_checks.CheckChangedLUCIConfigs(input_api, output_api))
result_factory = output_api.PresubmitPromptWarning
if input_api.is_committing:
result_factory = output_api.PresubmitError
results.extend(
input_api.canned_checks.CheckPatchFormatted(input_api,
output_api,
check_python=True))
input_api.canned_checks.CheckPatchFormatted(
input_api,
output_api,
check_python=True,
result_factory=result_factory))
results.extend(
input_api.canned_checks.CheckChangeHasDescription(
input_api, output_api))

View File

@ -17,6 +17,7 @@ import("//build_overrides/vulkan_common.gni")
# These are variables that are overridable by projects that include Dawn.
# The values in this file are the defaults for when we are building from
# Dawn's repository.
vvl_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src"
vvl_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src"
vvl_glslang_dir = "//third_party/vulkan-deps/glslang/src"

View File

@ -15,5 +15,4 @@
import("//build/config/ozone.gni")
# Dawn has no wayland third-party dir
use_system_libwayland = true
wayland_gn_dir = ""

336
dawn.json
View File

@ -53,7 +53,8 @@
"members": [
{"name": "compatible surface", "type": "surface", "optional": true},
{"name": "power preference", "type": "power preference", "default": "undefined"},
{"name": "force fallback adapter", "type": "bool", "default": "false"}
{"name": "force fallback adapter", "type": "bool", "default": "false"},
{"name": "compatibility mode", "type": "bool", "default": "false", "tags": ["dawn", "emscripten"]}
]
},
"request adapter status": {
@ -77,7 +78,13 @@
},
"adapter": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "get instance",
"tags": ["dawn"],
"returns": "instance"
},
{
"name": "get limits",
"returns": "bool",
@ -134,7 +141,8 @@
{"name": "name", "type": "char", "annotation": "const*", "length": "strlen"},
{"name": "driver description", "type": "char", "annotation": "const*", "length": "strlen"},
{"name": "adapter type", "type": "adapter type"},
{"name": "backend type", "type": "backend type"}
{"name": "backend type", "type": "backend type"},
{"name": "compatibility mode", "type": "bool", "default": "false", "tags": ["dawn", "emscripten"]}
]
},
"adapter type": {
@ -155,19 +163,21 @@
{"name": "required features count", "type": "uint32_t", "default": 0},
{"name": "required features", "type": "feature name", "annotation": "const*", "length": "required features count", "default": "nullptr"},
{"name": "required limits", "type": "required limits", "annotation": "const*", "optional": true},
{"name": "default queue", "type": "queue descriptor"}
{"name": "default queue", "type": "queue descriptor"},
{"name": "device lost callback", "type": "device lost callback", "default": "nullptr"},
{"name": "device lost userdata", "type": "void *", "default": "nullptr"}
]
},
"dawn toggles device descriptor": {
"dawn toggles descriptor": {
"tags": ["dawn", "native"],
"category": "structure",
"chained": "in",
"chain roots": ["device descriptor"],
"chain roots": ["instance descriptor", "device descriptor"],
"members": [
{"name": "force enabled toggles count", "type": "uint32_t", "default": 0},
{"name": "force enabled toggles", "type": "char", "annotation": "const*const*", "length": "force enabled toggles count"},
{"name": "force disabled toggles count", "type": "uint32_t", "default": 0},
{"name": "force disabled toggles", "type": "char", "annotation": "const*const*", "length": "force disabled toggles count"}
{"name": "enabled toggles count", "type": "uint32_t", "default": 0},
{"name": "enabled toggles", "type": "char", "annotation": "const*const*", "length": "enabled toggles count"},
{"name": "disabled toggles count", "type": "uint32_t", "default": 0},
{"name": "disabled toggles", "type": "char", "annotation": "const*const*", "length": "disabled toggles count"}
]
},
"dawn cache device descriptor" : {
@ -220,7 +230,7 @@
{"name": "binding", "type": "uint32_t"},
{"name": "buffer", "type": "buffer", "optional": true},
{"name": "offset", "type": "uint64_t", "default": "0"},
{"name": "size", "type": "uint64_t"},
{"name": "size", "type": "uint64_t", "default": "WGPU_WHOLE_SIZE"},
{"name": "sampler", "type": "sampler", "optional": true},
{"name": "texture view", "type": "texture view", "optional": true}
]
@ -445,6 +455,10 @@
"name": "get size",
"returns": "uint64_t"
},
{
"name": "get map state",
"returns": "buffer map state"
},
{
"name": "unmap"
},
@ -475,11 +489,22 @@
"emscripten_no_enum_table": true,
"values": [
{"value": 0, "name": "success"},
{"value": 1, "name": "error"},
{"value": 1, "name": "validation error"},
{"value": 2, "name": "unknown"},
{"value": 3, "name": "device lost"},
{"value": 4, "name": "destroyed before callback"},
{"value": 5, "name": "unmapped before callback"}
{"value": 5, "name": "unmapped before callback"},
{"value": 6, "name": "mapping already pending"},
{"value": 7, "name": "offset out of range"},
{"value": 8, "name": "size out of range"}
]
},
"buffer map state": {
"category": "enum",
"values": [
{"value": 0, "name": "unmapped"},
{"value": 1, "name": "pending"},
{"value": 2, "name": "mapped"}
]
},
"buffer usage": {
@ -550,6 +575,7 @@
},
"command encoder": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "finish",
@ -737,7 +763,10 @@
{"name": "line num", "type": "uint64_t"},
{"name": "line pos", "type": "uint64_t"},
{"name": "offset", "type": "uint64_t"},
{"name": "length", "type": "uint64_t"}
{"name": "length", "type": "uint64_t"},
{"name": "utf16 line pos", "type": "uint64_t"},
{"name": "utf16 offset", "type": "uint64_t"},
{"name": "utf16 length", "type": "uint64_t"}
]
},
"compilation message type": {
@ -760,6 +789,7 @@
},
"compute pass encoder": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "insert debug marker",
@ -808,15 +838,6 @@
{"name": "query index", "type": "uint32_t"}
]
},
{
"name": "dispatch",
"tags": ["deprecated"],
"args": [
{"name": "workgroupCountX", "type": "uint32_t"},
{"name": "workgroupCountY", "type": "uint32_t", "default": "1"},
{"name": "workgroupCountZ", "type": "uint32_t", "default": "1"}
]
},
{
"name": "dispatch workgroups",
"args": [
@ -825,14 +846,6 @@
{"name": "workgroupCountZ", "type": "uint32_t", "default": "1"}
]
},
{
"name": "dispatch indirect",
"tags": ["deprecated"],
"args": [
{"name": "indirect buffer", "type": "buffer"},
{"name": "indirect offset", "type": "uint64_t"}
]
},
{
"name": "dispatch workgroups indirect",
"args": [
@ -843,10 +856,6 @@
{
"name": "end"
},
{
"name": "end pass",
"tags": ["deprecated"]
},
{
"name": "end pipeline statistics query",
"tags": ["upstream", "emscripten"]
@ -916,7 +925,6 @@
"category": "structure",
"extensible": "in",
"tags": ["dawn"],
"_TODO": "support number as length input",
"members": [
{"name": "flip y", "type": "bool", "default": "false"},
{"name": "needs color space conversion", "type": "bool", "default": "false"},
@ -945,10 +953,11 @@
"emscripten_no_enum_table": true,
"values": [
{"value": 0, "name": "success"},
{"value": 1, "name": "error"},
{"value": 2, "name": "device lost"},
{"value": 3, "name": "device destroyed"},
{"value": 4, "name": "unknown"}
{"value": 1, "name": "validation error"},
{"value": 2, "name": "internal error"},
{"value": 3, "name": "device lost"},
{"value": 4, "name": "device destroyed"},
{"value": 5, "name": "unknown"}
]
},
"create render pipeline async callback": {
@ -995,7 +1004,10 @@
{
"name": "create error buffer",
"returns": "buffer",
"tags": ["dawn"]
"tags": ["dawn"],
"args": [
{"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
]
},
{
"name": "create command encoder",
@ -1085,17 +1097,15 @@
]
},
{
"name": "create swap chain",
"tags": ["dawn"],
"returns": "swap chain",
"name": "create error shader module",
"returns": "shader module",
"args": [
{"name": "surface", "type": "surface", "optional": true},
{"name": "descriptor", "type": "swap chain descriptor", "annotation": "const*"}
{"name": "descriptor", "type": "shader module descriptor", "annotation": "const*"},
{"name": "error message", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "create swap chain",
"tags": ["upstream", "emscripten"],
"returns": "swap chain",
"args": [
{"name": "surface", "type": "surface"},
@ -1159,15 +1169,21 @@
"tags": ["dawn"]
},
{
"name": "lose for testing",
"name": "force loss",
"args": [
{"name": "type", "type": "device lost reason"},
{"name": "message", "type": "char", "annotation": "const*", "length": "strlen"}
],
"tags": ["dawn"]
},
{
"name": "tick",
"no autolock": true,
"tags": ["dawn"]
},
{
"name": "set uncaptured error callback",
"no autolock": true,
"args": [
{"name": "callback", "type": "error callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
@ -1175,6 +1191,7 @@
},
{
"name": "set logging callback",
"no autolock": true,
"tags": ["dawn"],
"args": [
{"name": "callback", "type": "logging callback"},
@ -1183,6 +1200,8 @@
},
{
"name": "set device lost callback",
"no autolock": true,
"tags": ["deprecated"],
"args": [
{"name": "callback", "type": "device lost callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
@ -1196,7 +1215,6 @@
},
{
"name": "pop error scope",
"returns": "bool",
"args": [
{"name": "callback", "type": "error callback"},
{"name": "userdata", "type": "void", "annotation": "*"}
@ -1208,6 +1226,21 @@
"args": [
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen"}
]
},
{
"name": "validate texture descriptor",
"tags": ["dawn"],
"args": [
{"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
]
},
{
"name": "get supported surface usage",
"tags": ["dawn"],
"returns": "texture usage",
"args": [
{"name": "surface", "type": "surface"}
]
}
]
},
@ -1246,6 +1279,7 @@
{"name": "max texture dimension 3D", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max texture array layers", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max bind groups", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max bindings per bind group", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max dynamic uniform buffers per pipeline layout", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max dynamic storage buffers per pipeline layout", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max sampled textures per shader stage", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
@ -1258,11 +1292,13 @@
{"name": "min uniform buffer offset alignment", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "min storage buffer offset alignment", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max vertex buffers", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max buffer size", "type": "uint64_t", "default": "WGPU_LIMIT_U64_UNDEFINED"},
{"name": "max vertex attributes", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max vertex buffer array stride", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max inter stage shader components", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max inter stage shader variables", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max color attachments", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max color attachment bytes per sample", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max compute workgroup storage size", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max compute invocations per workgroup", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
{"name": "max compute workgroup size x", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"},
@ -1298,7 +1334,8 @@
"category": "enum",
"values": [
{"value": 0, "name": "validation"},
{"value": 1, "name": "out of memory"}
{"value": 1, "name": "out of memory"},
{"value": 2, "name": "internal"}
]
},
"error type": {
@ -1308,8 +1345,9 @@
{"value": 0, "name": "no error"},
{"value": 1, "name": "validation"},
{"value": 2, "name": "out of memory"},
{"value": 3, "name": "unknown"},
{"value": 4, "name": "device lost"}
{"value": 3, "name": "internal"},
{"value": 4, "name": "unknown"},
{"value": 5, "name": "device lost"}
]
},
"logging type": {
@ -1322,6 +1360,15 @@
{"value": 3, "name": "error"}
]
},
"extent 2D": {
"category": "structure",
"tags": ["dawn"],
"_TODO": "crbug.com/1316671: Remove default value of 'width' after chromium side chagnes landed",
"members": [
{"name": "width", "type": "uint32_t", "default": 0},
{"name": "height", "type": "uint32_t", "default": 1}
]
},
"extent 3D": {
"category": "structure",
"members": [
@ -1344,9 +1391,27 @@
{
"name": "destroy",
"returns": "void"
},
{
"name": "expire",
"returns": "void"
},
{
"name": "refresh",
"returns": "void"
}
]
},
"external texture rotation":{
"category": "enum",
"tags": ["dawn"],
"values": [
{"value": 0, "name": "rotate 0 degrees"},
{"value": 1, "name": "rotate 90 degrees"},
{"value": 2, "name": "rotate 180 degrees"},
{"value": 3, "name": "rotate 270 degrees"}
]
},
"external texture descriptor": {
"category": "structure",
"extensible": "in",
@ -1355,6 +1420,8 @@
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
{"name": "plane 0", "type": "texture view"},
{"name": "plane 1", "type": "texture view", "optional": true},
{"name": "visible origin", "type": "origin 2D"},
{"name": "visible size", "type": "extent 2D"},
{"name": "do yuv to rgb conversion only", "type": "bool", "default": "false"},
{"name": "yuv to rgb conversion matrix", "type": "float", "annotation": "const*",
"length": 12, "optional": true},
@ -1363,7 +1430,9 @@
{"name": "dst transfer function parameters", "type": "float", "annotation": "const*",
"length": 7},
{"name": "gamut conversion matrix", "type": "float", "annotation": "const*",
"length": 9}
"length": 9},
{"name": "flip y", "type": "bool", "default": "false"},
{"name": "rotation", "type": "external texture rotation", "default": "rotate 0 degrees"}
]
},
"feature name": {
@ -1378,11 +1447,19 @@
{"value": 6, "name": "texture compression ETC2"},
{"value": 7, "name": "texture compression ASTC"},
{"value": 8, "name": "indirect first instance"},
{"value": 9, "name": "shader f16"},
{"value": 10, "name": "RG11B10 ufloat renderable"},
{"value": 11, "name": "BGRA8 unorm storage"},
{"value": 12, "name": "float32 filterable"},
{"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]},
{"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]},
{"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]},
{"value": 1004, "name": "dawn native", "tags": ["dawn", "native"]},
{"value": 1005, "name": "chromium experimental dp4a", "tags": ["dawn"]}
{"value": 1005, "name": "chromium experimental dp4a", "tags": ["dawn"]},
{"value": 1006, "name": "timestamp query inside passes", "tags": ["dawn"]},
{"value": 1007, "name": "implicit device synchronization", "tags": ["dawn", "native"]},
{"value": 1008, "name": "surface capabilities", "tags": ["dawn"]},
{"value": 1009, "name": "transient attachments", "tags": ["dawn"]}
]
},
"filter mode": {
@ -1420,6 +1497,16 @@
{"name": "aspect", "type": "texture aspect", "default": "all"}
]
},
"image copy external texture": {
"category": "structure",
"extensible": "in",
"tags": ["dawn"],
"members": [
{"name": "external texture", "type": "external texture"},
{"name": "origin", "type": "origin 3D"},
{"name": "natural size", "type": "extent 2D"}
]
},
"index format": {
"category": "enum",
"values": [
@ -1430,6 +1517,7 @@
},
"instance": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "create surface",
@ -1439,8 +1527,7 @@
]
},
{
"name": "process events",
"tags": ["upstream", "emscripten"]
"name": "process events"
},
{
"name": "request adapter",
@ -1457,16 +1544,6 @@
"extensible": "in",
"members": []
},
"dawn instance descriptor": {
"tags": ["dawn", "native"],
"category": "structure",
"chained": "in",
"chain roots": ["instance descriptor"],
"members": [
{"name": "additional runtime search paths count", "type": "uint32_t", "default": 0},
{"name": "additional runtime search paths", "type": "char", "annotation": "const*const*", "length": "additional runtime search paths count"}
]
},
"vertex attribute": {
"category": "structure",
"extensible": false,
@ -1512,7 +1589,6 @@
},
"mipmap filter mode": {
"category": "enum",
"tags": ["upstream"],
"values": [
{"value": 0, "name": "nearest"},
{"value": 1, "name": "linear"}
@ -1534,6 +1610,14 @@
{"name": "z", "type": "uint32_t", "default": "0"}
]
},
"origin 2D": {
"category": "structure",
"tags": ["dawn"],
"members": [
{"name": "x", "type": "uint32_t", "default": "0"},
{"name": "y", "type": "uint32_t", "default": "0"}
]
},
"pipeline layout": {
"category": "object",
"methods": [
@ -1701,6 +1785,17 @@
{"name": "options", "type": "copy texture for browser options", "annotation": "const*"}
]
},
{
"name": "copy external texture for browser",
"extensible": "in",
"tags": ["dawn"],
"args": [
{"name": "source", "type": "image copy external texture", "annotation": "const*"},
{"name": "destination", "type": "image copy texture", "annotation": "const*"},
{"name": "copy size", "type": "extent 3D", "annotation": "const*"},
{"name": "options", "type": "copy texture for browser options", "annotation": "const*"}
]
},
{
"name": "set label",
"returns": "void",
@ -1736,11 +1831,21 @@
},
"render bundle": {
"category": "object"
"category": "object",
"methods": [
{
"name": "set label",
"returns": "void",
"args": [
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen"}
]
}
]
},
"render bundle encoder": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "set pipeline",
@ -1810,7 +1915,7 @@
"name": "set vertex buffer",
"args": [
{"name": "slot", "type": "uint32_t"},
{"name": "buffer", "type": "buffer"},
{"name": "buffer", "type": "buffer", "optional": true},
{"name": "offset", "type": "uint64_t", "default": "0"},
{"name": "size", "type": "uint64_t", "default": "WGPU_WHOLE_SIZE"}
]
@ -1870,7 +1975,6 @@
{"name": "resolve target", "type": "texture view", "optional": true},
{"name": "load op", "type": "load op"},
{"name": "store op", "type": "store op"},
{"name": "clear color", "type": "color", "default": "{ NAN, NAN, NAN, NAN }", "tags": ["deprecated"]},
{"name": "clear value", "type": "color"}
]
},
@ -1881,12 +1985,10 @@
{"name": "view", "type": "texture view"},
{"name": "depth load op", "type": "load op", "default": "undefined"},
{"name": "depth store op", "type": "store op", "default": "undefined"},
{"name": "clear depth", "type": "float", "default": "NAN", "tags": ["deprecated"]},
{"name": "depth clear value", "type": "float", "default": "0"},
{"name": "depth clear value", "type": "float", "default": "NAN"},
{"name": "depth read only", "type": "bool", "default": "false"},
{"name": "stencil load op", "type": "load op", "default": "undefined"},
{"name": "stencil store op", "type": "store op", "default": "undefined"},
{"name": "clear stencil", "type": "uint32_t", "default": "0", "tags": ["deprecated"]},
{"name": "stencil clear value", "type": "uint32_t", "default": "0"},
{"name": "stencil read only", "type": "bool", "default": "false"}
]
@ -1915,6 +2017,7 @@
},
"render pass encoder": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "set pipeline",
@ -1967,8 +2070,8 @@
{
"name": "execute bundles",
"args": [
{"name": "bundles count", "type": "uint32_t"},
{"name": "bundles", "type": "render bundle", "annotation": "const*", "length": "bundles count"}
{"name": "bundle count", "type": "uint32_t"},
{"name": "bundles", "type": "render bundle", "annotation": "const*", "length": "bundle count"}
]
},
{
@ -2023,7 +2126,7 @@
"name": "set vertex buffer",
"args": [
{"name": "slot", "type": "uint32_t"},
{"name": "buffer", "type": "buffer"},
{"name": "buffer", "type": "buffer", "optional": true},
{"name": "offset", "type": "uint64_t", "default": "0"},
{"name": "size", "type": "uint64_t", "default": "WGPU_WHOLE_SIZE"}
]
@ -2065,10 +2168,6 @@
{
"name": "end"
},
{
"name": "end pass",
"tags": ["deprecated"]
},
{
"name": "end pipeline statistics query",
"tags": ["upstream", "emscripten"]
@ -2176,8 +2275,8 @@
"extensible": "in",
"members": [
{"name": "format", "type": "texture format"},
{"name": "depth write enabled", "type": "bool", "default": "false"},
{"name": "depth compare", "type": "compare function", "default": "always"},
{"name": "depth write enabled", "type": "bool"},
{"name": "depth compare", "type": "compare function"},
{"name": "stencil front", "type": "stencil face state"},
{"name": "stencil back", "type": "stencil face state"},
{"name": "stencil read mask", "type": "uint32_t", "default": "0xFFFFFFFF"},
@ -2264,8 +2363,7 @@
{"name": "address mode w", "type": "address mode", "default": "clamp to edge"},
{"name": "mag filter", "type": "filter mode", "default": "nearest"},
{"name": "min filter", "type": "filter mode", "default": "nearest"},
{"name": "mipmap filter", "type": "filter mode", "default": "nearest", "tags": ["dawn", "emscripten"]},
{"name": "mipmap filter", "type": "mipmap filter mode", "default": "nearest", "tags": ["upstream"]},
{"name": "mipmap filter", "type": "mipmap filter mode", "default": "nearest"},
{"name": "lod min clamp", "type": "float", "default": "0.0f"},
{"name": "lod max clamp", "type": "float", "default": "1000.0f"},
{"name": "compare", "type": "compare function", "default": "undefined"},
@ -2323,8 +2421,18 @@
"chained": "in",
"chain roots": ["shader module descriptor"],
"members": [
{"name": "source", "type": "char", "annotation": "const*", "length": "strlen", "tags": ["dawn", "emscripten"]},
{"name": "code", "type": "char", "annotation": "const*", "length": "strlen", "tags": ["upstream"]}
{"name": "source", "type": "char", "annotation": "const*", "length": "strlen", "default": "nullptr", "optional": true, "tags": ["dawn", "emscripten"]},
{"name": "code", "type": "char", "annotation": "const*", "length": "strlen", "default": "nullptr", "optional": true, "tags": ["dawn", "emscripten"]},
{"name": "code", "type": "char", "annotation": "const*", "length": "strlen", "default": "nullptr", "tags": ["upstream"]}
]
},
"dawn shader module SPIRV options descriptor": {
"category": "structure",
"chained": "in",
"chain roots": ["shader module descriptor"],
"tags": ["dawn"],
"members": [
{"name": "allow non uniform derivatives", "type": "bool", "default": "false"}
]
},
"shader stage": {
@ -2361,6 +2469,7 @@
},
"surface": {
"category": "object",
"no autolock": true,
"methods": [
{
"name": "get preferred format",
@ -2466,17 +2575,8 @@
"swap chain": {
"category": "object",
"methods": [
{
"name": "configure",
"tags": ["dawn"],
"args": [
{"name": "format", "type": "texture format"},
{"name": "allowed usage", "type": "texture usage"},
{"name": "width", "type": "uint32_t"},
{"name": "height", "type": "uint32_t"}
]
},
{"name": "get current texture view", "returns": "texture view"},
{"name": "get current texture", "returns": "texture"},
{"name": "present"}
]
},
@ -2489,8 +2589,7 @@
{"name": "format", "type": "texture format"},
{"name": "width", "type": "uint32_t"},
{"name": "height", "type": "uint32_t"},
{"name": "present mode", "type": "present mode"},
{"name": "implementation", "type": "uint64_t", "default": 0, "tags": ["deprecated"]}
{"name": "present mode", "type": "present mode"}
]
},
"s type": {
@ -2514,10 +2613,13 @@
{"value": 14, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
{"value": 15, "name": "render pass descriptor max draw count"},
{"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
{"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]},
{"value": 1003, "name": "dawn encoder internal usage descriptor", "tags": ["dawn"]},
{"value": 1004, "name": "dawn instance descriptor", "tags": ["dawn", "native"]},
{"value": 1005, "name": "dawn cache device descriptor", "tags": ["dawn", "native"]}
{"value": 1005, "name": "dawn cache device descriptor", "tags": ["dawn", "native"]},
{"value": 1006, "name": "dawn adapter properties power preference", "tags": ["dawn", "native"]},
{"value": 1007, "name": "dawn buffer descriptor error info from wire client", "tags": ["dawn"]},
{"value": 1008, "name": "dawn toggles descriptor", "tags": ["dawn", "native"]},
{"value": 1009, "name": "dawn shader module SPIRV options descriptor", "tags": ["dawn"]}
]
},
"texture": {
@ -2584,15 +2686,6 @@
{"value": 4, "name": "plane 1 only", "tags": ["dawn"]}
]
},
"texture component type": {
"category": "enum",
"values": [
{"value": 0, "name": "float"},
{"value": 1, "name": "sint"},
{"value": 2, "name": "uint"},
{"value": 3, "name": "depth comparison"}
]
},
"texture data layout": {
"category": "structure",
"extensible": "in",
@ -2745,7 +2838,7 @@
{"value": 4, "name": "texture binding"},
{"value": 8, "name": "storage binding"},
{"value": 16, "name": "render attachment"},
{"value": 32, "name": "present", "tags": ["dawn"]}
{"value": 32, "name": "transient attachment", "tags": ["dawn"]}
]
},
"texture view descriptor": {
@ -2832,13 +2925,6 @@
"type": "size_t",
"value": "SIZE_MAX"
},
"stride undefined" : {
"category": "constant",
"tags": ["deprecated"],
"_TODO": "crbug.com/dawn/520: Remove WGPU_STRIDE_UNDEFINED in favor of WGPU_COPY_STRIDE_UNDEFINED.",
"type": "uint32_t",
"value": "(0xffffffffUL)"
},
"copy stride undefined" : {
"category": "constant",
"type": "uint32_t",
@ -2920,5 +3006,23 @@
"members": [
{"name": "use internal usages", "type": "bool", "default": "false"}
]
},
"dawn adapter properties power preference": {
"category": "structure",
"chained": "out",
"chain roots": ["adapter properties"],
"tags": ["dawn"],
"members": [
{"name": "power preference", "type": "power preference", "default": "undefined"}
]
},
"dawn buffer descriptor error info from wire client": {
"category": "structure",
"chained": "in",
"chain roots": ["buffer descriptor"],
"tags": ["dawn"],
"members": [
{"name": "out of memory", "type": "bool", "default": "false"}
]
}
}

View File

@ -19,21 +19,21 @@
"commands": {
"buffer map async": [
{ "name": "buffer id", "type": "ObjectId" },
{ "name": "buffer id", "type": "ObjectId", "id_type": "buffer" },
{ "name": "request serial", "type": "uint64_t" },
{ "name": "mode", "type": "map mode" },
{ "name": "offset", "type": "uint64_t"},
{ "name": "size", "type": "uint64_t"}
],
"buffer update mapped data": [
{ "name": "buffer id", "type": "ObjectId" },
{ "name": "buffer id", "type": "ObjectId", "id_type": "buffer" },
{ "name": "write data update info length", "type": "uint64_t" },
{ "name": "write data update info", "type": "uint8_t", "annotation": "const*", "length": "write data update info length", "skip_serialize": true},
{ "name": "offset", "type": "uint64_t"},
{ "name": "size", "type": "uint64_t"}
],
"device create buffer": [
{ "name": "device id", "type": "ObjectId" },
{ "name": "device id", "type": "ObjectId", "id_type": "device" },
{ "name": "descriptor", "type": "buffer descriptor", "annotation": "const*" },
{ "name": "result", "type": "ObjectHandle", "handle_type": "buffer" },
{ "name": "read handle create info length", "type": "uint64_t" },
@ -42,19 +42,19 @@
{ "name": "write handle create info", "type": "uint8_t", "annotation": "const*", "length": "write handle create info length", "skip_serialize": true}
],
"device create compute pipeline async": [
{ "name": "device id", "type": "ObjectId" },
{ "name": "device id", "type": "ObjectId", "id_type": "device"},
{ "name": "request serial", "type": "uint64_t" },
{ "name": "pipeline object handle", "type": "ObjectHandle", "handle_type": "compute pipeline"},
{ "name": "descriptor", "type": "compute pipeline descriptor", "annotation": "const*"}
],
"device create render pipeline async": [
{ "name": "device id", "type": "ObjectId" },
{ "name": "device id", "type": "ObjectId", "id_type": "device" },
{ "name": "request serial", "type": "uint64_t" },
{ "name": "pipeline object handle", "type": "ObjectHandle", "handle_type": "render pipeline"},
{ "name": "descriptor", "type": "render pipeline descriptor", "annotation": "const*"}
],
"device pop error scope": [
{ "name": "device id", "type": "ObjectId" },
{ "name": "device id", "type": "ObjectId", "id_type": "device" },
{ "name": "request serial", "type": "uint64_t" }
],
"destroy object": [
@ -62,19 +62,19 @@
{ "name": "object id", "type": "ObjectId" }
],
"queue on submitted work done": [
{ "name": "queue id", "type": "ObjectId" },
{ "name": "queue id", "type": "ObjectId", "id_type": "queue" },
{ "name": "signal value", "type": "uint64_t" },
{ "name": "request serial", "type": "uint64_t" }
],
"queue write buffer": [
{"name": "queue id", "type": "ObjectId" },
{"name": "buffer id", "type": "ObjectId" },
{"name": "queue id", "type": "ObjectId", "id_type": "queue" },
{"name": "buffer id", "type": "ObjectId", "id_type": "buffer" },
{"name": "buffer offset", "type": "uint64_t"},
{"name": "data", "type": "uint8_t", "annotation": "const*", "length": "size", "wire_is_data_only": true},
{"name": "size", "type": "uint64_t"}
],
"queue write texture": [
{"name": "queue id", "type": "ObjectId" },
{"name": "queue id", "type": "ObjectId", "id_type": "queue" },
{"name": "destination", "type": "image copy texture", "annotation": "const*"},
{"name": "data", "type": "uint8_t", "annotation": "const*", "length": "data size", "wire_is_data_only": true},
{"name": "data size", "type": "uint64_t"},
@ -82,17 +82,17 @@
{"name": "writeSize", "type": "extent 3D", "annotation": "const*"}
],
"shader module get compilation info": [
{ "name": "shader module id", "type": "ObjectId" },
{ "name": "shader module id", "type": "ObjectId", "id_type": "shader module" },
{ "name": "request serial", "type": "uint64_t" }
],
"instance request adapter": [
{ "name": "instance id", "type": "ObjectId" },
{ "name": "instance id", "type": "ObjectId", "id_type": "instance" },
{ "name": "request serial", "type": "uint64_t" },
{ "name": "adapter object handle", "type": "ObjectHandle", "handle_type": "adapter"},
{ "name": "options", "type": "request adapter options", "annotation": "const*" }
{ "name": "options", "type": "request adapter options", "annotation": "const*", "optional": true }
],
"adapter request device": [
{ "name": "adapter id", "type": "ObjectId" },
{ "name": "adapter id", "type": "ObjectId", "id_type": "adapter" },
{ "name": "request serial", "type": "uint64_t" },
{ "name": "device object handle", "type": "ObjectHandle", "handle_type": "device"},
{ "name": "descriptor", "type": "device descriptor", "annotation": "const*" }
@ -189,6 +189,7 @@
"BufferMapAsync",
"BufferGetConstMappedRange",
"BufferGetMappedRange",
"BufferGetMapState",
"BufferGetSize",
"BufferGetUsage",
"DeviceCreateBuffer",
@ -218,15 +219,19 @@
"TextureGetUsage"
],
"client_handwritten_commands": [
"AdapterGetInstance",
"BufferDestroy",
"BufferUnmap",
"DeviceCreateErrorBuffer",
"DeviceCreateQuerySet",
"DeviceCreateSwapChain",
"DeviceCreateTexture",
"DeviceCreateErrorTexture",
"DeviceGetAdapter",
"DeviceGetQueue",
"DeviceInjectError"
"DeviceGetSupportedSurfaceUsage",
"DeviceInjectError",
"SwapChainGetCurrentTexture"
],
"client_special_objects": [
"Adapter",
@ -236,6 +241,7 @@
"QuerySet",
"Queue",
"ShaderModule",
"SwapChain",
"Texture"
],
"server_custom_pre_handler_commands": [

View File

@ -73,6 +73,9 @@ The most common GN build option is `is_debug=true/false`; otherwise
On macOS you'll want to add the `use_system_xcode=true` in most cases.
(and if you're a googler please get XCode from go/xcode).
To generate a Microsoft Visual Studio solution, add `ide=vs2022` and
`ninja-executable=<dawn parent directory>\dawn\third_party\ninja\ninja.exe`.
The .sln file will be created in the output directory specified.
### Fuzzers on MacOS
If you are attempting fuzz, using `TINT_BUILD_FUZZERS=ON`, the version of llvm

View File

@ -2,11 +2,11 @@
Dawn relies on a lot of code generation to produce boilerplate code, especially webgpu.h-related code. They start by reading some JSON files (and sometimes XML too), process the data into an in-memory representation that's then used by some [Jinja2](https://jinja.palletsprojects.com/) templates to generate the code. This is similar to the model/view separation in Web development.
Generators are based on [generator_lib.py](../generator/generator_lib.py) which provides facilities for integrating in build systems and using Jinja2. Templates can be found in [`generator/templates`](../generator/templates) and the generated files are in `out/<Debug/Release/foo>/gen/src` when building Dawn in standalone. Generated files can also be found in [Chromium's code search](https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/dawn/src/).
Generators are based on [generator_lib.py](../../generator/generator_lib.py) which provides facilities for integrating in build systems and using Jinja2. Templates can be found in [`generator/templates`](../../generator/templates) and the generated files are in `out/<Debug/Release/foo>/gen/src` when building Dawn in standalone. Generated files can also be found in [Chromium's code search](https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/dawn/src/).
## Dawn "JSON API" generators
Most of the code generation is done from [`dawn.json`](../dawn.json) which is a JSON description of the WebGPU API with extra annotation used by some of the generators. The code for all the "Dawn JSON" generators is in [`dawn_json_generator.py`](../generator/dawn_json_generator.py) (with templates in the regular template dir).
Most of the code generation is done from [`dawn.json`](../../dawn.json) which is a JSON description of the WebGPU API with extra annotation used by some of the generators. The code for all the "Dawn JSON" generators is in [`dawn_json_generator.py`](../../generator/dawn_json_generator.py) (with templates in the regular template dir).
At this time it is used to generate:
@ -76,6 +76,8 @@ A **record** is a list of **record members**, each of which is a dictionary with
- `"name"` a string
- `"return_type"` (default to no return type) a string that's the name of the return type.
- `"arguments"` a **record**, so an array of **record members**
- `"no autolock"`: a boolean flag (default is false) indicates that the method's generated code won't automatically do thread synchronization. This flag can only be true on device or device child objects currently.
- `"no autolock"`: a boolean flag (default is false) to indicate that the object's generated code won't automatically do thread synchronization. This will override individual method's `"no autolock"` flag. This flag can only be true on device or device child objects currently.
**`"constant"`**
- `"type"`: a string, the name of the base data type
@ -87,7 +89,7 @@ A **record** is a list of **record members**, each of which is a dictionary with
## Dawn "wire" generators
The generator for the pieces of dawn_wire need additional data which is found in [`dawn_wire_json`](../dawn_wire.json). Examples of pieces that are generated are:
The generator for the pieces of dawn_wire need additional data which is found in [`dawn_wire_json`](../../dawn_wire.json). Examples of pieces that are generated are:
- `WireCmd.cpp/.h` the most important piece: the meat of the serialization / deserialization code for WebGPU structures and commands
- `ServerHandlers/Doers.cpp` that does the complete handling of all regular WebGPU methods in the server
@ -110,4 +112,13 @@ The schema of `dawn_wire.json` is a dictionary with the following keys:
## OpenGL loader generator
The code to load OpenGL entrypoints from a `GetProcAddress` function is generated from [`gl.xml`](../third_party/khronos/gl.xml) and the [list of extensions](../src/dawn/native/opengl/supported_extensions.json) it supports.
The code to load OpenGL entrypoints from a `GetProcAddress` function is generated from [`gl.xml`](../../third_party/khronos/gl.xml) and the [list of extensions](../../src/dawn/native/opengl/supported_extensions.json) it supports.
## Dawn lpmfuzz generator
One of Dawn's Fuzzers utilizes the information in [`dawn.json`, `dawn_wire.json`, `dawn_lpm.json`] to generate the `.proto` and `.cpp` files required for a [libprotobuf-mutator fuzzer](https://github.com/google/libprotobuf-mutator) that fuzzes Dawn Wire Server's stack with more effectiveness in some areas than plain libfuzzer.
At this time it is used to generate:
- the `dawn_lpm.proto` file used to describe the grammar for the fuzzer
- the serializer `DawnLPMSerializer.cpp` that takes an arbitrary number of protobuf structures that were defined in `dawn_lpm.proto` and serializes them to be passed to `DawnWireServer::HandleCommands`.

View File

@ -1,3 +1,49 @@
# Debugging Dawn
(TODO)
## Toggles
There are various debug-related Toggles that can help diagnose issues. Useful debug toggles:
- `dump_shaders`: Log input WGSL shaders and translated backend shaders (MSL/ HLSL/DXBC/DXIL / SPIR-V).
- `disable_symbol_renaming`: As much as possible, disable renaming of symbols (variables, function names, etc.). This can make dumped shaders more readable.
- `emit_hlsl_debug_symbols`: Sets the D3DCOMPILE_SKIP_OPTIMIZATION and D3DCOMPILE_DEBUG compilation flags when compiling HLSL code.
- `use_user_defined_labels_in_backend`: Forward object labels to the backend so that they can be seen in native debugging tools like RenderDoc, PIX, or Mac Instruments.
Toggles may be enabled/disabled in different ways.
- **In code:**
Use extension struct `DawnTogglesDescriptor` chained on `DeviceDescriptor`.
For example:
```c++
const char* const enabledToggles[] = {"dump_shaders", "disable_symbol_renaming"};
wgpu::DawnTogglesDescriptor deviceTogglesDesc;
deviceTogglesDesc.enabledToggles = enabledToggles;
deviceTogglesDesc.enabledTogglesCount = 2;
wgpu::DeviceDescriptor deviceDescriptor;
deviceDescriptor.nextInChain = &deviceTogglesDesc;
```
- **Command-line for Chrome**
Run Chrome with command line flags`--enable-dawn-features` and/or `--disable-dawn-features` to force enable/disable toggles. Toggles should be comma-delimited.
For example:
`--enable-dawn-features=dump_shaders,disable_symbol_renaming`
- **Command-line for dawn_end2end_tests/dawn_unittests**
Run Dawn test binaries with command line flags`--enable-toggles` and/or `--disable-toggles` to force enable/disable toggles. Toggles should be comma-delimited.
For example:
`dawn_end2end_tests --enable-toggles=dump_shaders,disable_symbol_renaming`
## Environment Variables
- `DAWN_DEBUG_BREAK_ON_ERROR`
Errors in WebGPU are reported asynchronously which may make debugging difficult because at the time an error is reported, you can't easily create a breakpoint to inspect the callstack in your application.
Setting `DAWN_DEBUG_BREAK_ON_ERROR` to a non-empty, non-zero value will execute a debug breakpoint
instruction ([`dawn::Breakpoint()`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/dawn/src/dawn/common/Assert.cpp?q=dawn::Breakpoint)) as soon as any type of error is generated.

View File

@ -9,11 +9,11 @@ Example of backend facilities are GPU memory allocators or the backing API funct
### Error Handling
Dawn (dawn_native) uses the [Error.h](../src/dawn/native/Error.h) error handling to robustly handle errors.
Dawn (dawn_native) uses the [Error.h](../../src/dawn/native/Error.h) error handling to robustly handle errors.
With `DAWN_TRY` errors bubble up all the way to, and are "consumed" by the entry-point that was called by the application.
Error consumption uses `Device::ConsumeError` that expose them via the WebGPU "error scopes" and can also influence the device lifecycle by notifying of a device loss, or triggering a device loss..
See [Error.h](../src/dawn/native/Error.h) for more information about using errors.
See [Error.h](../../src/dawn/native/Error.h) for more information about using errors.
### Device Lifecycle
@ -26,7 +26,7 @@ The device lifecycle is a bit more complicated than other objects in Dawn for mu
- A device can become "disconnected" when a TDR or hot-unplug happens.
In this case, destruction of the device doesn't need to wait on GPU commands to finish because they just disappeared.
There is a state machine `State` defined in [Device.h](../src/dawn/native/Device.h) that controls all of the above.
There is a state machine `State` defined in [Device.h](../../src/dawn/native/Device.h) that controls all of the above.
The most common state is `Alive` when there are potentially GPU commands executing.
Initialization of a device looks like the following:
@ -62,24 +62,24 @@ Toggles can be queried using `DeviceBase::IsToggleEnabled`:
bool useRenderPass = device->IsToggleEnabled(Toggle::UseD3D12RenderPass);
```
Toggles are defined in a table in [Toggles.cpp](../src/dawn/native/Toggles.cpp) that also includes their name and description.
The name can be used to force enabling of a toggle or, at the contrary, force the disabling of a toogle.
Toggles are defined in a table in [Toggles.cpp](../../src/dawn/native/Toggles.cpp) that also includes their name and description.
The name can be used to require enabling of a toggle or, at the contrary, require the disabling of a toogle.
This is particularly useful in tests so that the two sides of a code path can be tested (for example using D3D12 render passes and not).
Here's an example of a test that is run in the D3D12 backend both with the D3D12 render passes forcibly disabled, and in the default configuration.
Here's an example of a test that is run in the D3D12 backend both with the D3D12 render passes required to be disabled, and in the default configuration.
```
DAWN_INSTANTIATE_TEST(RenderPassTest,
D3D12Backend(),
D3D12Backend({}, {"use_d3d12_render_pass"}));
// The {} is the list of force enabled toggles, {"..."} the force disabled ones.
// The {} is the list of required enabled toggles, {"..."} the required disabled ones.
```
The initialization order of toggles looks as follows:
The toggles state of a device is decided by the adapter when creating it. The steps of device toggles state decision looks as follows:
- The toggles overrides from the device descriptor are applied.
- The frontend device default toggles are applied (unless already overriden).
- The backend device default toggles are applied (unless already overriden) using `DeviceBase::SetToggle`
- The backend device can ignore overriden toggles if it can't support them by using `DeviceBase::ForceSetToggle`
- The device toggles state initialized to required device toggles from the DawnTogglesDescriptor chained in device descriptor.
- The frontend (i.e. not backend-specific) default toggles are set (unless already required) using `TogglesState::Default`.
- Any backend device toggle that not supported is forced set to a proper state in `Adapter::SetupBackendDeviceToggles` using `TogglesState::ForceSet`.
- The backend device default toggles are applied (unless already set) in `Adapter::SetupBackendDeviceToggles` using `TogglesState::Default`.
Forcing toggles should only be done when there is no "safe" option for the toggle.
This is to avoid crashes during testing when the tests try to use both sides of a toggle.

View File

@ -0,0 +1,20 @@
# Surface Capabilities
The `surface-capabilities` feature allows querying a surface's capabilities and creating a swap chain with additional usage flags.
Additional functionality:
- Adds `wgpu::Device::GetSupportedSurfaceUsage(wgpu::Surface)` method for querying the surface's supported usage flags. One or the combination of these flags can be used to create a swap chain.
Example Usage:
```
wgpu::TextureUsage supportedUsage = device.GetSupportedSurfaceUsage(surface);
wgpu::SwapChainDescriptor desc = {};
// set usage flags.
desc.usage = supportedUsage;
device.CreateSwapChain(surface, &desc);
```
Notes:
- If this feature is not enabled, only `wgpu::TextureUsage::RenderAttachment` flag is allowed to be used in `wgpu::SwapChainDescriptor::usage`.

View File

@ -0,0 +1,24 @@
# Transient Attachments
The `transient-attachments` feature allows creation of attachments that allow
render pass operations to stay in tile memory, avoiding VRAM traffic and
potentially avoiding VRAM allocation for the textures.
Example Usage:
```
wgpu::TextureDescriptor desc;
desc.format = wgpu::TextureFormat::RGBA8Unorm;
desc.size = {1, 1, 1};
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TransientAttachment;
auto transientTexture = device.CreateTexture(&desc);
// Can now create views from the texture to serve as transient attachments, e.g.
// as color attachments in a render pipeline.
```
Notes:
- Only supported usage is wgpu::TextureUsage::RenderAttachment |
wgpu::TextureUsage::TransientAttachment
- It is not possible to load from or store to TextureViews that are used as
transient attachments

View File

@ -9,7 +9,7 @@ Dawn uses Chromium's continuous integration (CI) infrastructure to continually r
For additional information on GPU testing in Chromium, please see [[chromium/src]//docs/gpu/gpu_testing_bot_details.md](https://chromium.googlesource.com/chromium/src.git/+/main/docs/gpu/gpu_testing_bot_details.md).
## Dawn CI/Try Builders
Dawn builders are specified in [[dawn]//infra/config/global/cr-buildbucket.cfg](../infra/config/global/cr-buildbucket.cfg). This file contains a few mixins such as `clang`, `no_clang`, `x64`, `x86`, `debug`, `release` which are used to specify the bot dimensions and build properties (builder_mixins.recipe.properties). At the time of writing, we have the following builders:
Dawn builders are specified in [[dawn]//infra/config/global/cr-buildbucket.cfg](../../infra/config/global/generated/cr-buildbucket.cfg). This file contains a few mixins such as `clang`, `no_clang`, `x64`, `x86`, `debug`, `release` which are used to specify the bot dimensions and build properties (builder_mixins.recipe.properties). At the time of writing, we have the following builders:
- [dawn/try/presubmit](https://ci.chromium.org/p/dawn/builders/try/presubmit)
- [dawn/try/linux-clang-dbg-x64](https://ci.chromium.org/p/dawn/builders/try/linux-clang-dbg-x64)
- [dawn/try/linux-clang-dbg-x86](https://ci.chromium.org/p/dawn/builders/try/linux-clang-dbg-x86)
@ -23,16 +23,16 @@ Dawn builders are specified in [[dawn]//infra/config/global/cr-buildbucket.cfg](
There are additional `chromium/try` builders, but those are described later in this document.
These bots are defined in both buckets luci.dawn.ci and luci.dawn.try, though their ACL permissions differ. luci.dawn.ci bots will be scheduled regularly based on [[dawn]//infra/config/global/luci-scheduler.cfg](../infra/config/global/luci-scheduler.cfg). luci.dawn.try bots will be triggered on the CQ based on [[dawn]//infra/config/global/commit-queue.cfg](../infra/config/global/commit-queue.cfg).
These bots are defined in both buckets luci.dawn.ci and luci.dawn.try, though their ACL permissions differ. luci.dawn.ci bots will be scheduled regularly based on [[dawn]//infra/config/global/luci-scheduler.cfg](../../infra/config/global/generated/luci-scheduler.cfg). luci.dawn.try bots will be triggered on the CQ based on [[dawn]//infra/config/global/commit-queue.cfg](../../infra/config/global/generated/commit-queue.cfg).
One particular note is `buckets.swarming.builder_defaults.recipe.name: "dawn"` which specifies these use the [`dawn.py`](https://source.chromium.org/search/?q=file:recipes/dawn.py) build recipe.
Build status for both CI and Try builders can be seen at this [console](https://ci.chromium.org/p/dawn) which is generated from [[dawn]//infra/config/global/luci-milo.cfg](../infra/config/global/luci-milo.cfg).
Build status for both CI and Try builders can be seen at this [console](https://ci.chromium.org/p/dawn) which is generated from [[dawn]//infra/config/global/luci-milo.cfg](../../infra/config/global/generated/luci-milo.cfg).
## Dawn Build Recipe
The [`dawn.py`](https://cs.chromium.org/search/?q=file:recipes/dawn.py) build recipe is simple and intended only for testing compilation and unit tests. It does the following:
1. Checks out Dawn standalone and dependencies
2. Builds based on the `builder_mixins.recipe.properties` coming from the builder config in [[dawn]//infra/config/global/cr-buildbucket.cfg](../infra/config/global/cr-buildbucket.cfg).
2. Builds based on the `builder_mixins.recipe.properties` coming from the builder config in [[dawn]//infra/config/global/cr-buildbucket.cfg](../../infra/config/global/generated/cr-buildbucket.cfg).
3. Runs the `dawn_unittests` on that same bot.
## Dawn Chromium-Based CI Waterfall Bots
@ -48,7 +48,7 @@ The Builder and Tester bots are additionally configured at [[chromium/tools/buil
Finally, builds on these waterfall bots are automatically scheduled based on the configuration in [[chromium/src]//infra/config/buckets/ci.star](https://source.chromium.org/search?q=file:ci.star%20%22Dawn%20Linux%20x64%20Builder%22). Note that the Tester bots are `triggered_by` the Builder bots.
## Dawn Chromium-Based Tryjobs
[[dawn]//infra/config/global/commit-queue.cfg](../infra/config/global/commit-queue.cfg) declares additional tryjob builders which are defined in the Chromium workspace. The reason for this separation is that jobs sent to these bots rely on the Chromium infrastructure for doing builds and triggering jobs on bots with GPU hardware in swarming.
[[dawn]//infra/config/global/commit-queue.cfg](../../infra/config/global/generated/commit-queue.cfg) declares additional tryjob builders which are defined in the Chromium workspace. The reason for this separation is that jobs sent to these bots rely on the Chromium infrastructure for doing builds and triggering jobs on bots with GPU hardware in swarming.
At the time of writing, the bots for Dawn CLs are:
- [chromium/try/linux-dawn-rel](https://ci.chromium.org/p/chromium/builders/try/linux-dawn-rel)

View File

@ -4,31 +4,32 @@ This repository contains the implementation of Dawn, which is itself composed of
## Directory structure
- [`dawn.json`](../dawn.json): contains a description of the native WebGPU in JSON form. It is the data model that's used by the code generators.
- [`dawn_wire.json`](../dawn_wire.json): contains additional information used to generate `dawn_wire` files, such as commands in addition to regular WebGPU commands.
- [`examples`](../examples): a small collection of samples using the native WebGPU API. They were mostly used when bringing up Dawn for the first time, and to test the `WGPUSwapChain` object.
- [`generator`](../generator): directory containg the code generators and their templates. Generators are based on Jinja2 and parse data-models from JSON files.
- [`dawn_json_generator.py`](../generator/dawn_json_generator.py): the main code generator that outputs the WebGPU headers, C++ wrapper, client-server implementation, etc.
- [`templates`](../generator/templates): Jinja2 templates for the generator, with subdirectories for groups of templates that are all used in the same library.
- [`infra`](../infra): configuration file for the commit-queue infrastructure.
- [`scripts`](../scripts): contains a grab-bag of files that are used for building Dawn, in testing, etc.
- [`src`](../src):
- [`dawn`](../src/dawn): root directory for Dawn code
- [`common`](../src/dawn/common): helper code that is allowed to be used by Dawn's core libraries, `dawn_native` and `dawn_wire`. Also allowed for use in all other Dawn targets.
- [`fuzzers`](../src/dawn/fuzzers): various fuzzers for Dawn that are running in [Clusterfuzz](https://google.github.io/clusterfuzz/).
- [`native`](../src/dawn/native): code for the implementation of WebGPU on top of graphics APIs. Files in this folder are the "frontend" while subdirectories are "backends".
- [`dawn.json`](../../dawn.json): contains a description of the native WebGPU in JSON form. It is the data model that's used by the code generators.
- [`dawn_wire.json`](../../dawn_wire.json): contains additional information used to generate `dawn_wire` files, such as commands in addition to regular WebGPU commands.
- [`generator`](../../generator): directory containg the code generators and their templates. Generators are based on Jinja2 and parse data-models from JSON files.
- [`dawn_json_generator.py`](../../generator/dawn_json_generator.py): the main code generator that outputs the WebGPU headers, C++ wrapper, client-server implementation, etc.
- [`templates`](../../generator/templates): Jinja2 templates for the generator, with subdirectories for groups of templates that are all used in the same library.
- [`include`](../../include):
- [`dawn`](../../include/dawn): public headers with subdirectories for each library. Note that some headers are auto-generated and not present directly in the directory.
- [`infra`](../../infra): configuration file for the commit-queue infrastructure.
- [`scripts`](../../scripts): contains a grab-bag of files that are used for building Dawn, in testing, etc.
- [`src`](../../src):
- [`dawn`](../../src/dawn): root directory for Dawn code
- [`common`](../../src/dawn/common): helper code that is allowed to be used by Dawn's core libraries, `dawn_native` and `dawn_wire`. Also allowed for use in all other Dawn targets.
- [`fuzzers`](../../src/dawn/fuzzers): various fuzzers for Dawn that are running in [Clusterfuzz](https://google.github.io/clusterfuzz/).
- [`native`](../../src/dawn/native): code for the implementation of WebGPU on top of graphics APIs. Files in this folder are the "frontend" while subdirectories are "backends".
- `<backend>`: code for the implementation of the backend on a specific graphics API, for example `d3d12`, `metal` or `vulkan`.
- [`tests`](../src/dawn/tests):
- [`end2end`](../src/dawn/tests/end2end): tests for the execution of the WebGPU API and require a GPU to run.
- [`perf_tests`](../src/dawn/tests/perf_tests): benchmarks for various aspects of Dawn.
- [`unittests`](../src/dawn/tests/unittests): code unittests of internal classes, but also by extension WebGPU API tests that don't require a GPU to run.
- [`validation`](../src/dawn/tests/unittests/validation): WebGPU validation tests not using the GPU (frontend tests)
- [`white_box`](../src/dawn/tests/white_box): tests using the GPU that need to access the internals of `dawn_native` or `dawn_wire`.
- [`wire`](../src/dawn/wire): code for an implementation of WebGPU as a client-server architecture.
- [`utils`](../src/dawn/utils): helper code to use Dawn used by tests and samples but disallowed for `dawn_native` and `dawn_wire`.
- [`platform`](../src/dawn/platform): definition of interfaces for dependency injection in `dawn_native` or `dawn_wire`.
- [`include`](../src/include): public headers with subdirectories for each library. Note that some headers are auto-generated and not present directly in the directory.
- [`third_party`](../third_party): directory where dependencies live as well as their buildfiles.
- [`samples`](../../src/dawn/samples): a small collection of samples using the native WebGPU API. They were mostly used when bringing up Dawn for the first time, and to test the `WGPUSwapChain` object.
- [`tests`](../../src/dawn/tests):
- [`end2end`](../../src/dawn/tests/end2end): tests for the execution of the WebGPU API and require a GPU to run.
- [`perf_tests`](../../src/dawn/tests/perf_tests): benchmarks for various aspects of Dawn.
- [`unittests`](../../src/dawn/tests/unittests): code unittests of internal classes, but also by extension WebGPU API tests that don't require a GPU to run.
- [`validation`](../../src/dawn/tests/unittests/validation): WebGPU validation tests not using the GPU (frontend tests)
- [`white_box`](../../src/dawn/tests/white_box): tests using the GPU that need to access the internals of `dawn_native` or `dawn_wire`.
- [`wire`](../../src/dawn/wire): code for an implementation of WebGPU as a client-server architecture.
- [`utils`](../../src/dawn/utils): helper code to use Dawn used by tests and samples but disallowed for `dawn_native` and `dawn_wire`.
- [`platform`](../../src/dawn/platform): definition of interfaces for dependency injection in `dawn_native` or `dawn_wire`.
- [`third_party`](../../third_party): directory where dependencies live as well as their buildfiles.
## Dawn Native (`dawn_native`)

View File

@ -11,7 +11,7 @@ use_dawn = true # Required to build Dawn
use_cfi_icall=false # Required because Dawn dynamically loads function pointers, and we don't sanitize them yet.
```
A Chromium checkout is required for the highest optimization flags. It is possible to build and run `dawn_perf_tests` from a standalone Dawn checkout as well, only using GN arg `is_debug=false`. For more information on building, please see [building.md](./building.md).
A Chromium checkout is required for the highest optimization flags. It is possible to build and run `dawn_perf_tests` from a standalone Dawn checkout as well, only using GN arg `is_debug=false`. For more information on building, please see [building.md](../building.md).
### Terminology

View File

@ -10,7 +10,7 @@ Vulkan is supported as best effort on other platforms (e.g. Windows and macOS).
**Required features**: `depthBiasClamp`, `fragmentStoresAndAtomics`, `fullDrawIndexUint32`, `imageCubeArray`, `independentBlend`, `sampleRateShading`, and either `textureCompressionBC` or both of `textureCompressionETC` and `textureCompressionASTC_LDR`.
**Required limites**: they are too detailed to describe here, but in general should be wildly supported.
**Required limits**: they are too detailed to describe here, but in general should be wildly supported.
See the [WebGPU limits](https://gpuweb.github.io/gpuweb/#limits) that mostly correspond to Vulkan limits.
**Operating system support**:

View File

@ -7,7 +7,7 @@ Requirements:
## Building Tint with coverage generation enabled
Follow the steps [to build Tint with CMake](../README.md), but include the additional `-DTINT_EMIT_COVERAGE=1` CMake flag.
Follow the steps [to build Tint with CMake](../building.md), but include the additional `-DDAWN_EMIT_COVERAGE=1` CMake flag.
## Generate coverage information

View File

@ -63,7 +63,7 @@ Quoting single word identifiers or keywords from the source is not discouraged.
**Don't:**
```
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable
shader.wgsl:5:11 error: type cannot be used in address space 'storage' as it is non-host-shareable
cond : bool;
^^^^
@ -72,7 +72,7 @@ shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is
**Do:**
```
shader.wgsl:5:11 error: type cannot be used in storage class 'storage' as it is non-host-shareable
shader.wgsl:5:11 error: type cannot be used in address space 'storage' as it is non-host-shareable
cond : bool;
^^^^

View File

@ -12,7 +12,7 @@ Specification work in the WebGPU group hasn't started.
## Pseudo-specification
This extension adds a new `push_constant` storage class that's only allowed on global variable declarations.
This extension adds a new `push_constant` address space that's only allowed on global variable declarations.
Push constant variables must only contain 32bit data types (or aggregates of such types).
Push constant variable declarations must not have an initializer.
It is an error for a entry point to statically use more than one `push_constant` variable.

411
docs/tint/ir.md Normal file
View File

@ -0,0 +1,411 @@
# Intermediate Representation
As Tint has grown the number of transforms on the AST has grown. This
growth has lead to several issues:
1. Transforms rebuild the AST and SEM which causes slowness
1. Transforming in AST can be difficult as the AST is hard to work with
In order to address these goals, an IR is being introduced into Tint.
The IR is mutable, it holds the needed state in order to be transformed.
The IR is also translatable back into AST. It will be possible to
generate an AST, convert to IR, transform, and then rebuild a new AST.
This round-trip ability provides a few features:
1. Easy to integrate into current system by replacing AST transforms
piecemeal
1. Easier to test as the resulting AST can be emitted as WGSL and
compared.
The IR helps with the complexity of the AST transforms by limiting the
representations seen in the IR form. For example, instead of `for`,
`while` and `loop` constructs there is a single `loop` construct.
`alias` and `const_assert` nodes are not emitted into IR. Dead code is
eliminated during the IR construction.
As the IR can convert into AST, we could potentially simplify the
SPIRV-Reader by generating IR directly. The IR is closer to what SPIR-V
looks like, so maybe a simpler transform.
## Design
The IR breaks down into two fundamental pieces, the control flow and the
expression lists. While these can be thought of as separate pieces they
are linked in that the control flow blocks contain the expression lists.
A control flow block may use the result of an expression as the
condition.
The IR works together with the AST/SEM. There is an underlying
assumption that the source `Program` will live as long as the IR. The IR
holds pointers to data from the `Program`. This includes things like SEM
types, variables, statements, etc.
Transforming from AST to IR and back to AST is a lossy operation.
The resulting AST when converting back will not be the same as the
AST being provided. (e.g. all `for`, `while` and `loop` constructs coming
in will become `while` loops going out). This is intentional as it
greatly simplifies the number of things to consider in the IR. For
instance:
* No `alias` nodes
* No `const_assert` nodes
* All loops become `while` loops
* `if` statements may all become `if/else`
### Code Structure
The code is contained in the `src/tint/ir` folder and is broken down
into several classes. Note, the IR is a Tint _internal_ representation
and these files should _never_ appear in the public API.
#### Builder
The `Builder` class provides useful helper routines for creating IR
content. The Builder owns an `ir::Module`, it can be created with an
existing Module by moving it into the builder. The Module is moved from
the builder when it is complete.
#### Module
The top level of the IR is the `Module`. The module stores a list of
`functions`, `entry_points`, allocators and various other bits of
information needed by the IR. The `Module` also contains a pointer to
the `Program` which the IR was created from. The `Program` must outlive
the `Module`.
The `Module` provides two methods from moving two and from a `Program`.
The `Module::FromProgram` static method will take a `Program` and
construct an `ir::Module` from the contents. The resulting module class
then has a `ToProgram` method which will construct a new `Program` from
the `Module` contents.
#### BuilderImpl
The `BuilderImpl` is internally used by the `Module` to do the
conversion from a `Program` to a `Module`. This class should not be used
outside the `src/tint/ir` folder.
### Transforms
Similar to the AST a transform system is available for IR. The transform
has the same setup as the AST (and inherits from the same base transform
class.)
Note, not written yet.
### Scoping
The IR flattens scopes. This also means that the IR will rename shadow
variables to be uniquely named in the larger scoped block.
For an example of flattening:
```
{
var x = 1;
{
var y = 2;
}
}
```
becomes:
```
{
var x = 1;
var y = 2;
}
```
For an example of shadowing:
```
{
var x = 1;
if (true) {
var x = 2;
}
}
```
becomes:
```
{
var x = 1;
if true {
var x_1 = 2;
}
}
```
### Control Flow Blocks
At the top level, the AST is broken into a series of control flow nodes.
There are a limited set of flow nodes as compared to AST:
1. Block
1. Function
1. If statement
1. Loop statement
1. Switch statement
1. Terminator
As the IR is built a stack of control flow blocks is maintained. The
stack contains `function`, `loop`, `if` and `switch` control flow
blocks. A `function` is always the bottom element in the flow control
stack.
The current instruction block is tracked. The tracking is reset to
`nullptr` when a branch happens. This is used in the statement processing
in order to eliminate dead code. If the current block does not exist, or
has a branch target, then no further instructions can be added, which
means all control flow has branched and any subsequent statements can be
disregarded.
Note, this does have the effect that the inspector _must_ be run to
retrieve the module interface before converting to IR. This is because
phony assignments in dead code add variables into the interface.
```
var<storage> b;
fn a() {
return;
_ = b; // This pulls b into the module interface but would be
// dropped due to dead code removal.
}
```
#### Control Flow Block
A block is the simplest control flow node. It contains the instruction
lists for a given linear section of codes. A block only has one branch
statement which always happens at the end of the block. Note, the branch
statement is implicit, it doesn't show up in the expression list but is
encoded in the `branch_target`.
In almost every case a block does not branch to another block. It will
always branch to another control flow node. The exception to this rule
is blocks branching to the function end block.
#### Control Flow Function
A function control flow block has two targets associated with it, the
`start_target` and the `end_target`. Function flow starts at the
`start_target` and ends just before the `end_target`. The `end_target`
is always a terminator, it just marks the end of the function
(a return is a branch to the function `end_target`).
#### Control Flow If
The if flow node is an `if-else` structure. There are no `else-if`
entries, they get moved into the `else` of the `if`. The if control flow
node has three targets, the `true_target`, `false_target` and possibly a
`merge_target`.
The `merge_target` is possibly `nullptr`. This can happen if both
branches of the `if` call `return` for instance as the internal branches
would jump to the function `end_target`.
In all cases, the if node will have a `true_target` and a
`false_target`, the target block maybe just a branch to the
`merge_target` in the case where that branch of the if was empty.
#### Control Flow Loop
All of the loop structures in AST merge down to a single loop control
flow node. The loop contains the `start_target`, `continuing_target` and
a `merge_target`.
In the case of a loop, the `merge_target` always exists, but may
actually not exist in the control flow. The target is created in order
to have a branch for `continue` to branch too, but if the loop body does
a `return` then control flow may jump over that block completely.
The chain of blocks from the `start_target`, as long as it does not
`break` or `return` will branch to the `continuing_target`. The
`continuing_target` will possibly branch to the `merge_target` and will
branch to the `start_target` for the loop.
A while loop is decomposed as listed in the WGSL spec:
```
while (a < b) {
c += 1;
}
```
becomes:
```
loop {
if (!(a < b)) {
break;
}
c += 1;
}
```
A for loop is decomposed as listed in the WGSL spec:
```
for (var i = 0; i < 10; i++) {
c += 1;
}
```
becomes:
```
var i = 0;
loop {
if (!(i < 10)) {
break;
}
c += 1;
continuing {
i++;
}
}
```
#### Control Flow Switch
The switch control flow has a target block for each of the
`case/default` labels along with a `merge_target`. The `merge_target`
while existing, maybe outside the control flow if all of the `case`
branches `return`. The target exists in order to provide a `break`
target.
#### Control Flow Terminator
The terminator control flow is only used as the `end_target` of a
function. It does not contain instructions and is only used as a marker
for the exit of a function.
### Expression Lists.
Note, this section isn't fully formed as this has not been written at
this point.
The expression lists are all in SSA form. The SSA variables will keep
pointers back to the source AST variables in order for us to not require
PHI nodes and to make it easier to move back out of SSA form.
#### Expressions
All expressions in IR are single operations. There are no complex
expressions. Any complex expression in the AST is broke apart into the
simpler single operation components.
```
var a = b + c - (4 * k);
```
becomes:
```
%t0 = b + c
%t1 = 4 * k
%v0 = %t0 - %t1
```
This also means that many of the short forms `i += 1`, `i++` get
expanded into the longer form of `i = i + 1`.
##### Short-Circuit Expressions
The short-circuit expressions (e.g. `a && b`) will be convert into an
`if` structure control flow.
```
let c = a() && b()
```
becomes
```
let c = a();
if (c) {
c = b();
}
```
#### Registers
There are several types of registers used in the SSA form.
1. Constant Register
1. Temporary Register
1. Variable Register
1. Return Register
1. Function Argument Register
##### Constant Register
The constant register `%c` holds a constant value. All values in IR are
concrete, there are no abstract values as materialization has already
happened. Each constant register holds a single constant value (e.g.
`3.14`) and a pointee to the type (maybe? If needed.)
##### Temporary Register
The temporary register `%t` hold the results of a simple operation. The
temporaries are created as complex expressions are broken down into
pieces. The temporary register tracks the usage count for the register.
This allows a portion of a calculation to be pulled out when rebuilding
AST as a common calculation. If the temporary is used once it can be
re-combine back into a large expression.
##### Variable Register
The variable register `%v` potentially holds a pointer back to source
variables. So, while each value is written only once, if the pointer
back to an AST variable exists we can rebuild the variable that value
was originally created from and can assign back when converting to AST.
##### Return Register
Each function has a return register `%r` where the return value will be
stored before the final block branches to the `end_target`.
##### Function Argument Register
The function argument registers `%a` are used to store the values being
passed into a function call.
#### Type Information
The IR shares type information with the SEM. The types are the same, but
they may exist in different block allocations. The SEM types will be
re-used if they exist, but if the IR needs to create a new type it will
be created in the IRs type block allocator.
#### Loads / Stores and Deref
Note, have not thought about this. We should probably have explicit
load/store operations injected in the right spot, but don't know yet.
## Alternatives
Instead of going to a custom IR there are several possible other roads
that could be travelled.
### Mutable AST
Tint originally contained a mutable AST. This was converted to immutable
in order to allow processing over multiple threads and for safety
properties. Those desires still hold, the AST is public API, and we want
it to be as safe as possible, so keeping it immutable provides that
guarantee.
### Multiple Transforms With One Program Builder
Instead of generating an immutable AST after each transform, running
multiple transforms on the single program builder would remove some of
the performance penalties of going to and from immutable AST. While this
is true, the transforms use a combination of AST and SEM information.
When they transform they _do not_ create new SEM information. That
means, after a given transform, the SEM is out of date. In order to
re-generate the SEM the resolver needs to be rerun. Supporting this
would require being very careful on what transforms run together and
how they modify the AST.
### Adopt An Existing IR
There are already several IRs in the while, Mesa has NIR, LLVM has
LLVM IR. There are others, adopting one of those would remove the
requirements of writing and maintaining our own IR. While that is true,
there are several downsides to this re-use. The IRs are internal to the
library, so the API isn't public, LLVM IR changes with each iteration of
LLVM. This would require us to adapt the AST -> IR -> AST transform for
each modification of the IR.
They also end up being lower level then is strictly useful for us. While
the IR in Tint is a simplified form, we still have to be able to go back
to the high level structured form in order to emit the resulting HLSL,
MSL, GLSL, etc. (Only SPIR-V is a good match for the lowered IR form).
This transformation back is not a direction other IRs maybe interested
in so may have lost information, or require re-determining (determining
variables from SSA and PHI nodes for example).
Other technical reasons are the maintenance of BUILD.gn and CMake files
in order to integrate into our build systems, along with resulting
binary size questions from pulling in external systems.

68
docs/tint/layering.md Normal file
View File

@ -0,0 +1,68 @@
# Tint Source Layering
The `BUILD.gn` is setup with small source units for various components
in Tint. The hierarchy of sources almost matches to folder structure in
tint (except for `base` which is a mix of things in `src/tint` and
`src/tint/util`.
```
+-----------------------------------------+
| Readers | Writers |
+-----------------------------------------+
|
V
+-----------------------------------------+
| Val | Inspector | Transform |
+-----------------------------------------+
| |
+--------------+------------------------------+
| |
V V
+-----------------------------------------+ +-----------+
| AST | | Utils IO |
+-----------------------------------------+ +-----------+
| |
V |
+-----------------------------------------+ |
| Program | Sem | |
+-----------------------------------------+ |
| |
V |
+-----------------------------------------+ |
| AST Hdrs | |
| (program and sem cause a cycle) | |
+-----------------------------------------+ |
| |
V |
+-----------------------------------------+ |
| Clone Context Hdrs | |
| (program and sem cause a cycle) | |
+-----------------------------------------+ |
| |
V |
+-----------------------------------------+ |
| Constant | |
+-----------------------------------------+ |
| |
V |
+-----------------------------------------+ |
| Types | |
+-----------------------------------------+ |
| |
|------------------------------+
V
+-----------------------------------------+
| Symbols |
+-----------------------------------------+
|
V
+-----------------------------------------+
| Builtin |
+-----------------------------------------+
|
V
+-----------------------------------------+ +-------------+
| Utils | | Initializer |
+-----------------------------------------+ +-------------+
```

View File

@ -1,5 +1,87 @@
# Tint changes during Origin Trial
## Changes for M112
### Breaking changes
* Most builtin functions that return a value can no longer be used as a call statement. [tint:1844](crbug.com/tint/1844)
* The `sig` member of the return type of `frexp()` has been renamed to `fract`. [tint:1766](crbug.com/tint/1766)
* Calling a function with multiple pointer arguments that alias each other is now a error. [tint:1675](crbug.com/tint/1675)
* `type` deprecation has been removed. `alias` must be used now. [tint:1812](crbug.com/tint/1812)
* `static_assert` deprecation has been removed. `const_assert` must now be used. [tint:1807](crbug.com/tint/1807)
## Changes for M111
### New features
* The `workgroupUniformLoad` builtin function is now supported. [tint:1780](crbug.com/tint/1780)
* The `diagnostic` directive and `@diagnostic` attribute are now supported. [tint:1809](crbug.com/tint/1809)
* The attribute is currently only supported on function declarations.
### Breaking changes
* You may need to add parentheses to less-than or greater-than binary expressions that now parse as template lists. For example `a(b<c, d>e)` will need parentheses around `b<c` or `d>e`. [tint:1810](crbug.com/tint/1810).
* Uniformity analysis failures are now an error [tint:880](crbug.com/tint/880)
* The `derivative_uniformity` diagnostic filter can be used to modify the severity if needed.
## Deprecated Features
* The keyword to alias a type has been renamed from `type` to `alias`. [tint:1812](crbug.com/tint/1812)
* `static_assert` has been renamed to `const_assert`. [tint:1807](crbug.com/tint/1807)
## Changes for M110
### Breaking changes
* The `textureSampleLevel()` overload for `texture_external` has been removed. Use `textureSampleBaseClampToEdge()`. [tint:1671](crbug.com/tint/1671)
### Deprecated Features
* The `sig` member of the return type of `frexp()` has been renamed to `fract`. [tint:1757](crbug.com/tint/1757)
* Calling a function with multiple pointer arguments that alias each other is now a warning, and
will become an error in a future release. [tint:1675](crbug.com/tint/1675)
## Changes for M109
### Breaking changes
* `textureDimensions()`, `textureNumLayers()` and `textureNumLevels()` now return unsigned integers / vectors. [tint:1526](crbug.com/tint/1526)
* The `@stage` attribute has been removed. The short forms should be used
instead (`@vertex`, `@fragment`, or `@compute`). [tint:1503](crbug.com/tint/1503)
* Module-scope `let` is now an error. Use module-scope `const` instead. [tint:1580](crbug.com/tint/1584)
* Reserved words are now an error instead of a deprecation. [tint:1463](crbug.com/tint/1463)
* You may no longer use pointer parameters in `workgroup` address space. [tint:1721](crbug.com/tint/1721)
### New features
* Uniformity analysis failures are warnings again [tint:1728](crbug.com/tint/1728)
* You can now call texture builtins with a mix of signed and unsigned integer arguments. [tint:1733](crbug.com/tint/1733)
## Changes for M108
### New features
* `textureSampleBaseClampToEdge()` has been implemented. [tint:1671](crbug.com/tint/1671)
### Deprecated Features
* The `external_texture` overload of `textureSampleLevel()` has been deprecated. Use `textureSampleBaseClampToEdge()` instead. [tint:1671](crbug.com/tint/1671)
### Fixes
* Constant evaluation of type conversions where the value exceeds the limits of the target type have been fixed. [tint:1707](crbug.com/tint/1707)
## Changes for M107
### New features
* `saturate()` has been implemented. [tint:1591](crbug.com/tint/1591)
### Breaking changes
* Uniformity analysis failures are now an error [tint:880](crbug.com/tint/880)
* Indexing an array, vector or matrix with a compile-time expression that's out-of-bounds is now an error [tint:1665](crbug.com/tint/1665)
## Changes for M106
### New features

View File

@ -15,7 +15,7 @@ as variables at module scope.
## Vulkan SPIR-V today
SPIR-V for Vulkan models inputs and outputs as module-scope variables in
the Input and Output storage classes, respectively.
the Input and Output address spaces, respectively.
The `OpEntryPoint` instruction has a list of module-scope variables that must
be a superset of all the input and output variables that are statically

View File

@ -0,0 +1,558 @@
# Converting SPIR-V to WGSL
This document describes the challenges in converting SPIR-V into WGSL.
Note: Unless otherwise specified, the namespace for C++ code is
`tint::reader::spirv::`.
## Overall flow
1. Validate the SPIR-V input.
The SPIR-V module (binary blob) is validated against rules for
Vulkan 1.1, using the SPIRV-Tools validator.
This allows the rest of the flow to ignore invalid inputs.
However, the SPIR-V might still be rejected in a later step because:
- it uses features unavailable in WGSL, or
- the SPIR-V Reader is insufficiently smart, or
- the translated program tries to do something rejected by WGSL's rules
(which are checked by Tint's Resolver).
2. Load the SPIR-V binary into an in-memory representation.
The SPIR-V reader uses the in-memory representation of the SPIR-V
module defined by the SPIRV-Tools optimizer. That provides
convenient representation of basic structures such as:
- instructions
- types
- constants
- functions
- basic blocks
and provides analyses for:
- relating definitions to uses (spvtools::opt::analysis::DefUseMgr)
- types (spvtools::opt::analysis:TypeManager)
- constants (spvtools::opt::analysis:ConstantManager)
Note: The SPIR-V is not modified by the SPIR-V Reader.
3. Translate the SPIR-V module into Tint's AST.
The AST is valid for WGSL except for some small exceptions which are
cleaned up by transformations.
4. Post-process the AST to make it valid for WGSL.
Example:
- Rewrite strided arrays and matrices (remove `@stride` attribute)
- Rewrite atomic functions
- Remove unreachable statements, to satisfy WGSL's behaviour analysis.
## Overcoming mismatches between SPIR-V and WGSL
### Remapping builtin inputs and outputs
SPIR-V for Vulkan models builtin inputs and outputs as variables
in Input and Output storage classes.
WGSL builtin inputs are parameters to the entry point, and
builtin outputs are result values of the entry point.
See [spirv-input-output-variables.md](spirv-input-output-variables.md)
### We only care about `gl_Position` from `gl_PerVertex`
Glslang SPIR-V output for a vertex shader has a `gl_PerVertex`
output variable with four members:
- `gl_Position`
- `gl_PointSize`
- `gl_ClipDistance`
- `gl_CullDistance`
WGSL only supports the `position` builtin variable.
The SPIR-V Reader has a bunch of carveouts so it only generates the
position variable. In partcular, it tracks which expressions are actually
accesses into the per-vertex variable, and ignores accesses to other
parts of the structure, and remaps accesses of the position member.
### `gl_PointSize` must be 1.0
It's a WGSL rule. SPIR-V is more flexible, and the SPIR-V Reader
checks that any assignment to (the equivalent of) `gl_PointSize`
must the constant value 1.0.
### Remapping sample mask inputs and outputs
There's some shenanigans here I don't recall.
See the SkipReason enum.
### Integer signedness
In SPIR-V, the instruction determines the signedness of an operation,
not the types of its operands.
For example:
%uint = OpTypeInt 32 0 ; u32 type
%int = OpTypeInt 32 1 ; i32 type
%int_1 = OpConstant %int 1 ; WGSL 1i
%uint_2 = OpConstant %uint 2 ; WGSL 2u
; You can mix signs of an operand, and the instruction
; tells you the result type.
%sum_uint = OpIAdd %uint %int %int_1 %uint_2
%sum_int = OpIAdd %int %int %int_1 %uint_2
However, WGSL arithmetic tends to require the operands and
result type for an operation to all have the same signedness.
So the above might translate to WGSL as:
let sum_uint: u32 = bitcast<u32>(1i) + 2u;
let sum_int: i32 = 1i + bitcast<i32>(2u);
See:
* ParserImpl::RectifyOperandSignedness
* ParserImpl::RectifySecondOperandSignedness
* ParserImpl::RectifyForcedResultType
### Translating textures and samplers
SPIR-V textures and samplers are module-scope variables
in UniformConstant storage class.
These map directly to WGSL variables.
For a sampled-image operation, SPIR-V will:
- load the image value from a texture variable
- load the sampler value from a sampler variable
- form a "sampled image" value using `SpvOpSampledImage`
- then use that sampled image value in a image operation
such as `SpvOpImageSampleImplicitLod`
For an image operation that is not a sampled-image operation
(e.g. OpImageLoad or OpImageWrite), then the steps are similar
except without a sampler (clearly), and without invoking
`OpSampledImage`.
In contrast to the SPIR-V code pattern, the WGSL builtin requires
the texture and sampler value to be passed in as separate parameters.
Secondly, they are passed in by value, by naming the variables
themselves and relying on WGSL's "Load Rule" to pass the handle
value into the callee.
When the SPIR-V Reader translates a texture builtin, it traces
backward through the `OpSampledImage` operation (if any),
back through the load, and all the way back to the `OpVariable`
declaration. It does this for both the image/texture variable and
the sampler variable (if applicable). It then uses the names
of those variables as the corresponding arguments to the WGSL
texture builtin.
### Passing textures and samplers into helper functions
Glslang generates SPIR-V where texture and sampler formal parameters
are as pointer-to-UniformConstant.
WGSL models them as passing texture and sampler values themselves,
conceptually as opaque handles. This is similar to GLSL, but unlike
SPIR-V.
To support textures and samplers as arguments to user-defined functions,
we extend the tracing logic so it knows to bottom out at OpFunctionParameter.
Also, code that generates function declarations now understands formal
parameters declared as a pointer to uniform-constant as
well as direct image and sampler values.
Example GLSL compute shader:
#version 450
layout(set=0,binding=0) uniform texture2D im;
layout(set=0,binding=1) uniform sampler s;
vec4 helper(texture2D imparam, sampler sparam) {
return texture(sampler2D(imparam,sparam),vec2(0));
}
void main() {
vec4 v = helper(im,s);
}
SPIR-V generated by Glslang (Shaderc's glslc):
; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 10
; Bound: 32
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
OpSourceExtension "GL_GOOGLE_include_directive"
OpName %main "main"
OpName %helper_t21_p1_ "helper(t21;p1;"
OpName %imparam "imparam"
OpName %sparam "sparam"
OpName %v "v"
OpName %im "im"
OpName %s "s"
OpDecorate %im DescriptorSet 0
OpDecorate %im Binding 0
OpDecorate %s DescriptorSet 0
OpDecorate %s Binding 1
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
%_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7
%9 = OpTypeSampler
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
%v4float = OpTypeVector %float 4
%12 = OpTypeFunction %v4float %_ptr_UniformConstant_7 %_ptr_UniformConstant_9
%19 = OpTypeSampledImage %7
%v2float = OpTypeVector %float 2
%float_0 = OpConstant %float 0
%23 = OpConstantComposite %v2float %float_0 %float_0
%_ptr_Function_v4float = OpTypePointer Function %v4float
%im = OpVariable %_ptr_UniformConstant_7 UniformConstant
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
%main = OpFunction %void None %3
%5 = OpLabel
%v = OpVariable %_ptr_Function_v4float Function
%31 = OpFunctionCall %v4float %helper_t21_p1_ %im %s
OpStore %v %31
OpReturn
OpFunctionEnd
%helper_t21_p1_ = OpFunction %v4float None %12
%imparam = OpFunctionParameter %_ptr_UniformConstant_7
%sparam = OpFunctionParameter %_ptr_UniformConstant_9
%16 = OpLabel
%17 = OpLoad %7 %imparam
%18 = OpLoad %9 %sparam
%20 = OpSampledImage %19 %17 %18
%24 = OpImageSampleExplicitLod %v4float %20 %23 Lod %float_0
OpReturnValue %24
OpFunctionEnd
What the SPIR-V Reader currently generates:
@group(0) @binding(0) var im : texture_2d<f32>;
@group(0) @binding(1) var s : sampler;
fn helper_t21_p1_(imparam : texture_2d<f32>, sparam : sampler) -> vec4<f32> {
let x_24 : vec4<f32> = textureSampleLevel(imparam, sparam, vec2<f32>(0.0f, 0.0f), 0.0f);
return x_24;
}
fn main_1() {
var v : vec4<f32>;
let x_31 : vec4<f32> = helper_t21_p1_(im, s);
v = x_31;
return;
}
@compute @workgroup_size(1i, 1i, 1i)
fn main() {
main_1();
}
### Dimensionality mismatch in texture builtins
Vulkan SPIR-V is fairly forgiving in the dimensionality
of input coordinates and result values of texturing operations.
There is some localized rewriting of values to satisfy the overloads
of WGSL's texture builtin functions.
### Reconstructing structured control flow
This is subtle.
- Use structural dominance (but we didn't have the name at the time).
See SPIR-V 1.6 Rev 2 for updated definitions.
- See the big comment at the start of reader/spirv/function.cc
- See internal presentations.
Basically:
* Compute a "structured order" for structurally reachable basic blocks.
* Traversing in structured order, use a stack-based algorithn to
identify intervals of blocks corresponding to structured constructs.
For example, loop construct, continue construct, if-selection,
switch-selection, and case-construct. Constructs can be nested,
hence the need for a stack. This is akin to "drawing braces"
around statements, to form block-statements that will appear in
the output. This step performs some validation, which may now be
redundant with the SPIRV-Tools validator. This is defensive
programming, and some tests skip use of the SPIRV-Tools validator.
* Traversing in structured order, identify structured exits from the
constructs identified in the previous step. This determines what
control flow edges correspond to `break`, `continue`, and `return`,
as needed.
* Traversing in structured order, generate statements for instructions.
This uses a stack corresponding to nested constructs. The kind of
each construct being entered or exited determines emission of control
flow constructs (WGSL's `if`, `loop`, `continuing`, `switch`, `case`).
### Preserving execution order
An instruction inside a SPIR-V instruction is one of:
- control flow: see the previous section
- combinatorial: think of this as an ALU operation, i.e. the effect
is purely to evaluate a result value from the values of its operands.
It has no side effects, and is not affected by external state such
as memory or the actions of other invocations in its subgroup.
Examples: arithmetic, OpCopyObject
- interacts with memory or other invocations in some way.
Examples: load, store, atomics, barriers, (subgroup operations when we
get them)
- function calls: functions are not analyzed to see if they are pure,
so we assume function calls are non-combinatorial.
To preserve execution order, all non-combinatorial instructions must
be translated as their own separate statement. For example, an OpStore
maps to an assignment statement.
However, combinatorial instructions can be emitted at any point
in evaluation, provided data flow constraints are satisfied: input
values are available, and such that the resulting value is generated
in time for consumption by downstream uses.
The SPIR-V Reader uses a heuristic to choose when to emit combinatorial
values:
- if a combinatorial expression only has one use, *and*
- its use is in the same structured construct as its definition, *then*
- emit the expression at the place where it is consumed.
Otherwise, make a `let` declaration for the value.
Why:
- If a value has many uses, then computing it once can save effort.
Preserve that choice if it was made by an upstream optimizing compiler.
- If a value is consumed in a different structured construct, then the
site of its consumption may be inside a loop, and we don't want to
sink the computation into the loop, thereby causing spurious extra
evaluation.
This heuristic generates halfway-readable code, greatly reducing the
varbosity of code in the common case.
### Hoisting and phis
SPIR-V uses SSA (static single assignment). The key requirement is
that the definition of a value must dominate its uses.
WGSL uses lexical scoping.
It is easy enough for a human or an optimizing compiler to generate
SSA cases which do not map cleanly to a lexically scoped value.
Example pseudo-GLSL:
void main() {
if (cond) {
const uint x = 1;
} else {
return;
}
const uint y = x; // x's definition dominates this use.
}
This isn't valid GLSL and its analog would not be a valid WGSL
program because x is used outside the scope of its declaration.
Additionally, SSA uses `phi` nodes to transmit values from predecessor
basic blocks that would otherwise not be visible (because the
parent does not dominate the consuming basic block). An example
is sending the updated value of a loop induction variable back to
the top of the loop.
The SPIR-V reader handles these cases by tracking:
- where a value definition occurs
- the span of basic blocks, in structured order, where there
are uses of the value.
If the uses of a value span structured contructs which are not
contained by the construct containing the definition (or
if the value is a `phi` node), then we "hoist" the value
into a variable:
- create a function-scope variable at the top of the structured
construct that spans all the uses, so that all the uses
are in scope of that variable declaration.
- for a non-phi: generate an assignment to that variable corresponding
to the value definition in the original SPIR-V.
- for a phi: generate an assigment to that variable at the end of
each predecessor block for that phi, assigning the value to be
transmitted from that phi.
This scheme works for values which can be the stored in a variable.
It does not work for pointers. However, we don't think we need
to solve this case any time soon as it is uncommon or hard/impossible
to generate via standard tooling.
See https://crbug.com/tint/98 and https://crbug.com/tint/837
## Mapping types
SPIR-V has a recursive type system. Types are defined, given result IDs,
before any functions are defined, and before any constant values using
the corresponding types.
WGSL also has a recursive type system. However, except for structure types,
types are spelled inline at their uses.
## Texture and sampler types
SPIR-V image types map to WGSL types, but the WGSL type is determined
more by usage (what operations are performed on it) than by declaration.
For example, Vulkan ignores the "Depth" operand of the image type
declaration (OpTypeImage).
See [16.1 Image Operations Overview](https://registry.khronos.org/vulkan/specs/1.3/html/vkspec.html#_image_operations_overview).
Instead, we must infer that a texture is a depth texture because
it is used by image instructions using a depth-reference, e.g.
OpImageSampleDrefImplicitLod vs. OpImageSampleImplicitLod.
Similarly, SPIR-V only has one sampler type. The use of the
sampler determines whether it maps to a WGSL `sampler` or
`sampler_comparison` (for depth sampling).
The SPIR-V Reader scans uses of each texture and sampler
in the module to infer the appropriate target WGSL type.
See ParserImpl::RegisterHandleUsage
In Vulkan SPIR-V it is possible to use the same sampler for regular
sampling and depth-reference sampling. In this case the SPIR-V Reader
will infer a depth texture, but then the generated program will fail WGSL
validation.
For example, this GLSL fragment shader:
#version 450
layout(set=1,binding=0) uniform texture2D tInput;
layout(set=1,binding=1) uniform sampler s;
void main() {
vec4 v = texture(sampler2D(tInput,s),vec2(0));
float f = texture(sampler2DShadow(tInput,s),vec3(0));
}
Converts to this WGSL shader:
@group(1) @binding(0) var tInput : texture_depth_2d;
@group(1) @binding(1) var s : sampler_comparison;
fn main_1() {
var v : vec4<f32>;
var f : f32;
let x_23 : vec4<f32> = vec4<f32>(textureSample(tInput, s, vec2<f32>(0.0f, 0.0f)), 0.0f, 0.0f, 0.0f);
v = x_23;
let x_34 : f32 = textureSampleCompare(tInput, s, vec3<f32>(0.0f, 0.0f, 0.0f).xy, vec3<f32>(0.0f, 0.0f, 0.0f).z);
f = x_34;
return;
}
@fragment
fn main() {
main_1();
}
But then this fails validation:
error: no matching call to textureSample(texture_depth_2d, sampler_comparison, vec2<f32>)
15 candidate functions: ...
## References and pointers
SPIR-V has a pointer type.
A SPIR-V pointer type corresponds to a WGSL memory view. WGSL has two
memory view types: a reference type, and a pointer type.
See [spirv-ptr-ref.md](spirv-ptr-ref.md) for details on the translation.
## Mapping buffer types
Vulkan SPIR-V expresses a Uniform Buffer Object (UBO), or
a WGSL 'uniform buffer' as:
- an OpVariable in Uniform storage class
- its pointee type (store type) is a Block-decorated structure type
Vulkan SPIR-V has two ways to express a Shader Storage Buffer Object (SSBO),
or a WGSL 'storage buffer' as either deprecated-style:
- an OpVariable in Uniform storage class
- its pointee type (store type) is a BufferBlock-decorated structure type
or as new-style:
- an OpVariable in StorageBuffer storage class
- its pointee type (store type) is a Block-decorated structure type
Deprecated-style storage buffer was the only option in un-extended
Vulkan 1.0. It is generated by tools that want to generate code for
the broadest reach. This includes DXC.
New-style storage buffer requires the use of the `OpExtension
"SPV_KHR_storage_buffer_storage_class"` or SPIR-V 1.3 or later
(Vulkan 1.1 or later).
Additionally, a storage buffer in SPIR-V may be marked as NonWritable.
Perhaps surprisingly, this is typically done by marking *all* the
members of the top-level (Buffer)Block-decorated structure as NonWritable.
(This is the common translation because that's what Glslang does.)
Translation of uniform buffers is straightforward.
However, the SPIR-V Reader must support both the deprecated and the new
styles of storage buffers.
Additionally:
- a storage buffer with all NonWritable members is translated with `read`
access mode. This becomes a part of its WGSL reference type (and hence
corresponding pointer type).
- a storage buffer without all NonWritable members is translated with
an explicit `read_write` access mode. This becomes a part of its
WGSL reference type (and hence corresponding pointer type).
Note that read-only vs. read-write is a property of the pointee-type in SPIR-V,
but in WGSL it's part of the reference type (not the store type).
To handle this mismatch, the SPIR-V Reader has bookkeeping to map
each pointer value (inside a function) back to through to the originating
variable. This originating variable may be a buffer variable which then
tells us which address space and access mode to use for a locally-defined
pointer value.
Since baseline SPIR-V does not allow passing pointers to buffers into
user-defined helper functions, we don't need to handle this buffer type
remapping into function formal parameters.
## Mapping OpArrayLength
The OpArrayLength instruction takes a pointer to the enclosing
structure (the pointee type of the storage buffer variable).
But the WGSL arrayLength builtin variable takes a pointer to the
member inside that structure.
A small local adjustment is sufficient here.

View File

@ -14,7 +14,7 @@
* Do not use C++ exceptions
* Do not use C++ RTTI.
Instead, use `tint::Castable::As<T>()` from
Instead, use `tint::utils::Castable::As<T>()` from
[src/castable.h](../src/castable.h)
* Generally, avoid `assert`. Instead, issue a [diagnostic](../src/diagnostic.h)

View File

@ -141,7 +141,7 @@ TODO(dsinclair): Nested if's
## SPIR-V
TODO(dsinclair): Nested if's
# Storage classes
# Address spaces
TODO(dsinclair): do ...
# Storage buffers
@ -155,7 +155,7 @@ TODO(dsinclair): Rewrite with bools
## MSL
TODO(dsinclair): Rewrite with bools
# Input / Output storage class
# Input / Output address spaces
## HLSL
TODO(dsinclair): Structs and params

View File

@ -1,63 +0,0 @@
# 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.
import("../scripts/dawn_overrides_with_defaults.gni")
import("dawn_generator.gni")
# The list of directories in which to check for stale autogenerated files.
# It should include the list of all directories in which we ever generated
# files but we can't just put dawn_gen_root because there are more than
# autogenerated sources there.
_stale_dirs = [
"dawn",
"dawn/native",
"dawn/wire",
"mock",
"src",
]
_allowed_output_dirs_file =
"${dawn_gen_root}/removed_stale_autogen_files.allowed_output_dirs"
write_file(_allowed_output_dirs_file, dawn_allowed_gen_output_dirs)
_stale_dirs_file = "${dawn_gen_root}/removed_stale_autogen_files.stale_dirs"
write_file(_stale_dirs_file, _stale_dirs)
_stamp_file = "${dawn_gen_root}/removed_stale_autogen_files.stamp"
# An action that removes autogenerated files that aren't in allowed directories
# see dawn_generator.gni for more details.
action("remove_stale_autogen_files") {
script = "remove_files.py"
args = [
"--root-dir",
rebase_path(dawn_gen_root, root_build_dir),
"--allowed-output-dirs-file",
rebase_path(_allowed_output_dirs_file, root_build_dir),
"--stale-dirs-file",
rebase_path(_stale_dirs_file, root_build_dir),
"--stamp",
rebase_path(_stamp_file, root_build_dir),
]
# Have the "list of file" inputs as a dependency so that the action reruns
# as soon as they change.
inputs = [
_allowed_output_dirs_file,
_stale_dirs_file,
]
# Output a stamp file so we don't re-run this action on every build.
outputs = [ _stamp_file ]
}

View File

@ -27,6 +27,7 @@ if (NOT DAWN_JINJA2_DIR)
endif()
else()
message(STATUS "Dawn: using jinja2 at ${DAWN_JINJA2_DIR}")
message(STATUS "Dawn: using markupsafe at ${DAWN_MARKUPSAFE_DIR}")
endif()
# Function to invoke a generator_lib.py generator.
@ -54,6 +55,9 @@ function(DawnGenerator)
if (DAWN_JINJA2_DIR)
list(APPEND BASE_ARGS --jinja2-path ${DAWN_JINJA2_DIR})
endif()
if (DAWN_MARKUPSAFE_DIR)
list(APPEND BASE_ARGS --markupsafe-path ${DAWN_MARKUPSAFE_DIR})
endif()
# Call the generator to get the list of its dependencies.
execute_process(

View File

@ -15,41 +15,6 @@
import("../scripts/dawn_overrides_with_defaults.gni")
import("generator_lib.gni")
# Dawn used to put autogenerated files in a lot of different places. When we
# started to move them around, some compilation issues arised because some
# stale include files stayed in the build directory and were picked up.
# To counter this, now Dawn does the following:
#
# 1. The generated output file directory structure has to match the structure
# of the source tree, starting at dawn_gen_root (gen/ or
# gen/third_party/dawn depending on where we are).
# 2. include and dawn_gen_root/include has to match the structure of
# the source tree too.
# 3. Dawn files must use include relative to src/ or include such as
# "dawn/dawn.h" or "dawn/native/backend/BackendStuff.h".
#
# The allowed list below ensure 1). Include directory rules for Dawn ensure 3)
# and 2) is something we need to enforce in code review.
#
# However GN's toolchains automatically add some include directories for us
# which breaks 3) slightly. To avoid stale headers in for example
# dawn_gen_root/src/dawn/dawn/ to be picked up (instead of
# dawn_gen_root/src/dawn), we have a special action that removes files in
# disallowed gen directories.
dawn_allowed_gen_output_dirs = [
"src/dawn/",
"src/dawn/common/",
"src/dawn/native/",
"src/dawn/native/opengl/",
"src/dawn/wire/client/",
"src/dawn/wire/server/",
"src/dawn/wire/",
"include/dawn/",
"emscripten-bits/",
"webgpu-headers/",
]
# Template to help invoking Dawn code generators based on generator_lib
#
# dawn_generator("my_target_gen") {
@ -76,20 +41,16 @@ dawn_allowed_gen_output_dirs = [
#
template("dawn_generator") {
generator_lib_action(target_name) {
forward_variables_from(invoker, "*")
forward_variables_from(invoker, "*", [ "script" ])
script = get_path_info(invoker.script, "abspath")
# Set arguments required to find the python libraries for the generator
generator_lib_dir = "${dawn_root}/generator"
generator_lib_dir = get_path_info("${dawn_root}/generator", "abspath")
jinja2_path = dawn_jinja2_dir
# Force Dawn's autogenerated file structure to mirror exactly the source
# tree but start at ${dawn_gen_root} instead of ${dawn_root}
allowed_output_dirs = dawn_allowed_gen_output_dirs
custom_gen_dir = dawn_gen_root
# Make sure that we delete stale autogenerated file in directories that are
# no longer used by code generation to avoid include conflicts.
deps = [ "${dawn_root}/generator:remove_stale_autogen_files" ]
}
}
@ -119,3 +80,25 @@ template("dawn_json_generator") {
forward_variables_from(invoker, "*", [ "target" ])
}
}
template("dawn_json_lpm_generator") {
dawn_generator(target_name) {
script = "${dawn_root}/generator/dawn_json_generator.py"
# The base arguments for the generator: from this dawn.json, generate this
# target using templates in this directory.
args = [
"--dawn-json",
rebase_path("${dawn_root}/dawn.json", root_build_dir),
"--wire-json",
rebase_path("${dawn_root}/dawn_wire.json", root_build_dir),
"--lpm-json",
rebase_path("${dawn_root}/src/dawn/fuzzers/lpmfuzz/dawn_lpm.json",
root_build_dir),
"--targets",
invoker.target,
]
forward_variables_from(invoker, "*", [ "target" ])
}
}

View File

@ -181,6 +181,7 @@ class RecordMember:
self.optional = optional
self.is_return_value = is_return_value
self.handle_type = None
self.id_type = None
self.default_value = default_value
self.skip_serialize = skip_serialize
@ -188,9 +189,13 @@ class RecordMember:
assert self.type.dict_name == "ObjectHandle"
self.handle_type = handle_type
def set_id_type(self, id_type):
assert self.type.dict_name == "ObjectId"
self.id_type = id_type
Method = namedtuple('Method',
['name', 'return_type', 'arguments', 'json_data'])
Method = namedtuple(
'Method', ['name', 'return_type', 'arguments', 'autolock', 'json_data'])
class ObjectType(Type):
@ -308,6 +313,9 @@ def linked_record_members(json_data, types):
handle_type = m.get('handle_type')
if handle_type:
member.set_handle_type(types[handle_type])
id_type = m.get('id_type')
if id_type:
member.set_id_type(types[id_type])
members.append(member)
members_by_name[member.name.canonical_case()] = member
@ -331,17 +339,34 @@ def linked_record_members(json_data, types):
return members
def mark_lengths_non_serializable_lpm(record_members):
# Remove member length values from command metadata,
# these are set to the length of the protobuf array.
for record_member in record_members:
lengths = set()
for member in record_member.members:
lengths.add(member.length)
for member in record_member.members:
if member in lengths:
member.skip_serialize = True
############################################################
# PARSE
############################################################
def link_object(obj, types):
# Disable method's autolock if obj's "no autolock" = True
obj_scoped_autolock_enabled = not obj.json_data.get('no autolock', False)
def make_method(json_data):
arguments = linked_record_members(json_data.get('args', []), types)
autolock_enabled = obj_scoped_autolock_enabled and not json_data.get(
'no autolock', False)
return Method(Name(json_data['name']),
types[json_data.get('returns',
'void')], arguments, json_data)
types[json_data.get('returns', 'void')], arguments,
autolock_enabled, json_data)
obj.methods = [make_method(m) for m in obj.json_data.get('methods', [])]
obj.methods.sort(key=lambda method: method.name.canonical_case())
@ -371,7 +396,6 @@ def link_function(function, types):
function.arguments = linked_record_members(function.json_data['args'],
types)
# Sort structures so that if struct A has struct B as a member, then B is
# listed before A.
#
@ -566,6 +590,103 @@ def compute_wire_params(api_params, wire_json):
return wire_params
############################################################
# DAWN LPM FUZZ STUFF
############################################################
def compute_lpm_params(api_and_wire_params, lpm_json):
# Start with all commands in dawn.json and dawn_wire.json
lpm_params = api_and_wire_params.copy()
# Commands that are built through codegen
generated_commands = []
# All commands, including hand written commands that we can't generate
# through codegen
all_commands = []
# Remove blocklisted commands from protobuf generation params
blocklisted_cmds_proto = lpm_json.get('blocklisted_cmds')
custom_cmds_proto = lpm_json.get('custom_cmds')
for command in lpm_params['cmd_records']['command']:
blocklisted = command.name.get() in blocklisted_cmds_proto
custom = command.name.get() in custom_cmds_proto
if blocklisted:
continue
if not custom:
generated_commands.append(command)
all_commands.append(command)
# Set all fields that are marked as the "length" of another field to
# skip_serialize. The values passed by libprotobuf-mutator will cause
# an instant crash during serialization if these don't match the length
# of the data they are passing. These values aren't used in
# deserialization.
mark_lengths_non_serializable_lpm(
api_and_wire_params['cmd_records']['command'])
mark_lengths_non_serializable_lpm(
api_and_wire_params['by_category']['structure'])
lpm_params['cmd_records'] = {
'proto_generated_commands': generated_commands,
'proto_all_commands': all_commands,
'cpp_generated_commands': generated_commands,
'lpm_info': lpm_json.get("lpm_info")
}
return lpm_params
def as_protobufTypeLPM(member):
assert 'type' in member.json_data
if member.type.name.native:
typ = member.json_data['type']
cpp_to_protobuf_type = {
"bool": "bool",
"float": "float",
"double": "double",
"int8_t": "int32",
"int16_t": "int32",
"int32_t": "int32",
"int64_t": "int64",
"uint8_t": "uint32",
"uint16_t": "uint32",
"uint32_t": "uint32",
"uint64_t": "uint64",
}
assert typ in cpp_to_protobuf_type
return cpp_to_protobuf_type[typ]
return member.type.name.CamelCase()
# Helper that generates names for protobuf grammars from contents
# of dawn*.json like files. example: membera
def as_protobufNameLPM(*names):
# `descriptor` is a reserved keyword in lib-protobuf-mutator
if (names[0].concatcase() == "descriptor"):
return "desc"
return as_varName(*names)
# Helper to generate member accesses within C++ of protobuf objects
# example: cmd.membera().memberb()
def as_protobufMemberNameLPM(*names):
# `descriptor` is a reserved keyword in lib-protobuf-mutator
if (names[0].concatcase() == "descriptor"):
return "desc"
return ''.join([name.concatcase().lower() for name in names])
def unreachable_code():
assert False
#############################################################
# Generator
@ -698,16 +819,10 @@ def as_formatType(typ):
def c_methods(params, typ):
return typ.methods + [
x for x in [
Method(Name('reference'), params['types']['void'], [],
{'tags': ['dawn', 'emscripten']}),
Method(Name('release'), params['types']['void'], [],
{'tags': ['dawn', 'emscripten']}),
] if item_is_enabled(params['enabled_tags'], x.json_data)
and not item_is_disabled(params['disabled_tags'], x.json_data)
Method(Name('reference'), params['types']['void'], [], False, {}),
Method(Name('release'), params['types']['void'], [], False, {}),
]
def get_c_methods_sorted_by_name(api_params):
unsorted = [(as_MethodSuffix(typ.name, method.name), typ, method) \
for typ in api_params['by_category']['object'] \
@ -777,7 +892,7 @@ class MultiGeneratorFromDawnJSON(Generator):
def add_commandline_arguments(self, parser):
allowed_targets = [
'dawn_headers', 'cpp_headers', 'cpp', 'proc', 'mock_api', 'wire',
'native_utils'
'native_utils', 'dawn_lpmfuzz_cpp', 'dawn_lpmfuzz_proto'
]
parser.add_argument('--dawn-json',
@ -788,6 +903,10 @@ class MultiGeneratorFromDawnJSON(Generator):
default=None,
type=str,
help='The DAWN WIRE JSON definition to use.')
parser.add_argument("--lpm-json",
default=None,
type=str,
help='The DAWN LPM FUZZER definitions to use.')
parser.add_argument(
'--targets',
required=True,
@ -795,6 +914,7 @@ class MultiGeneratorFromDawnJSON(Generator):
help=
'Comma-separated subset of targets to output. Available targets: '
+ ', '.join(allowed_targets))
def get_file_renders(self, args):
with open(args.dawn_json) as f:
loaded_json = json.loads(f.read())
@ -806,6 +926,11 @@ class MultiGeneratorFromDawnJSON(Generator):
with open(args.wire_json) as f:
wire_json = json.loads(f.read())
lpm_json = None
if args.lpm_json:
with open(args.lpm_json) as f:
lpm_json = json.loads(f.read())
renders = []
params_dawn = parse_json(loaded_json,
@ -834,6 +959,11 @@ class MultiGeneratorFromDawnJSON(Generator):
'include/dawn/' + api + '_cpp_print.h',
[RENDER_PARAMS_BASE, params_dawn]))
renders.append(
FileRender('api_cpp_chained_struct.h',
'include/dawn/' + api + '_cpp_chained_struct.h',
[RENDER_PARAMS_BASE, params_dawn]))
if 'proc' in targets:
renders.append(
FileRender('dawn_proc.c', 'src/dawn/' + prefix + '_proc.c',
@ -1025,12 +1155,76 @@ class MultiGeneratorFromDawnJSON(Generator):
'src/dawn/wire/server/ServerPrototypes_autogen.inc',
wire_params))
if 'dawn_lpmfuzz_proto' in targets:
params_dawn_wire = parse_json(loaded_json,
enabled_tags=['dawn', 'deprecated'],
disabled_tags=['native'])
api_and_wire_params = compute_wire_params(params_dawn_wire,
wire_json)
fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
lpm_params = [
RENDER_PARAMS_BASE, params_dawn_wire, {
'as_protobufTypeLPM': as_protobufTypeLPM,
'as_protobufNameLPM': as_protobufNameLPM,
'unreachable': unreachable_code
}, api_and_wire_params, fuzzer_params
]
renders.append(
FileRender('dawn/fuzzers/lpmfuzz/dawn_lpm.proto',
'src/dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.proto',
lpm_params))
renders.append(
FileRender(
'dawn/fuzzers/lpmfuzz/dawn_object_types_lpm.proto',
'src/dawn/fuzzers/lpmfuzz/dawn_object_types_lpm_autogen.proto',
lpm_params))
if 'dawn_lpmfuzz_cpp' in targets:
params_dawn_wire = parse_json(loaded_json,
enabled_tags=['dawn', 'deprecated'],
disabled_tags=['native'])
api_and_wire_params = compute_wire_params(params_dawn_wire,
wire_json)
fuzzer_params = compute_lpm_params(api_and_wire_params, lpm_json)
lpm_params = [
RENDER_PARAMS_BASE, params_dawn_wire, {
'as_protobufMemberName': as_protobufMemberNameLPM,
'unreachable_code': unreachable_code
}, api_and_wire_params, fuzzer_params
]
renders.append(
FileRender(
'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.cpp',
'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.cpp',
lpm_params))
renders.append(
FileRender(
'dawn/fuzzers/lpmfuzz/DawnLPMSerializer.h',
'src/dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h',
lpm_params))
renders.append(
FileRender(
'dawn/fuzzers/lpmfuzz/DawnLPMConstants.h',
'src/dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h',
lpm_params))
return renders
def get_dependencies(self, args):
deps = [os.path.abspath(args.dawn_json)]
if args.wire_json != None:
deps += [os.path.abspath(args.wire_json)]
if args.lpm_json != None:
deps += [os.path.abspath(args.lpm_json)]
return deps

View File

@ -37,11 +37,6 @@
#
# jinja2_path: Optional Jinja2 installation path.
#
# allowed_output_dirs: Optional list of directories that are the only
# directories in which files of `outputs` are allowed to be (and not
# in children directories). Generation will fail if an output isn't
# in a directory in the list.
#
# root_dir: Optional root source dir for Python dependencies
# computation. Defaults to "${generator_lib_dir}/..". Any dependency
# outside of this directory is considered a system file and will be
@ -62,7 +57,7 @@ template("generator_lib_action") {
}
_generator_args += [
"--template-dir",
rebase_path(_template_dir),
rebase_path(_template_dir, root_build_dir),
]
if (defined(invoker.root_dir)) {
@ -75,7 +70,7 @@ template("generator_lib_action") {
if (defined(invoker.jinja2_path)) {
_generator_args += [
"--jinja2-path",
rebase_path(invoker.jinja2_path),
rebase_path(invoker.jinja2_path, root_build_dir),
]
}
@ -118,19 +113,6 @@ template("generator_lib_action") {
rebase_path(_expected_outputs_file, root_build_dir),
]
# Check that all of the outputs are in a directory that's allowed. This is
# useful to keep the list of directories in sink with other parts of the
# build.
if (defined(invoker.allowed_output_dirs)) {
_allowed_output_dirs_file = "${_gen_dir}/${target_name}.allowed_output_dirs"
write_file(_allowed_output_dirs_file, invoker.allowed_output_dirs)
_generator_args += [
"--allowed-output-dirs-file",
rebase_path(_allowed_output_dirs_file, root_build_dir),
]
}
# The code generator invocation that will write the JSON tarball, check the
# outputs are what's expected and write a depfile for Ninja.
action(_json_tarball_target) {

View File

@ -90,6 +90,16 @@ except ValueError:
# --jinja2-path isn't passed, ignore the exception and just import Jinja2
# assuming it already is in the Python PATH.
pass
kMarkupSafePath = '--markupsafe-path'
try:
markupsafe_path_argv_index = sys.argv.index(kMarkupSafePath)
# Add parent path for the import to succeed.
path = os.path.join(sys.argv[markupsafe_path_argv_index + 1], os.pardir)
sys.path.insert(1, path)
except ValueError:
# --markupsafe-path isn't passed, ignore the exception and just import
# assuming it already is in the Python PATH.
pass
import jinja2
@ -236,6 +246,11 @@ def run_generator(generator):
default=None,
type=str,
help='Additional python path to set before loading Jinja2')
parser.add_argument(
kMarkupSafePath,
default=None,
type=str,
help='Additional python path to set before loading MarkupSafe')
parser.add_argument(
'--output-json-tarball',
default=None,
@ -258,12 +273,6 @@ def run_generator(generator):
type=str,
help=('Optional source root directory for Python dependency '
'computations'))
parser.add_argument(
'--allowed-output-dirs-file',
default=None,
type=str,
help=("File containing a list of allowed directories where files "
"can be output."))
parser.add_argument(
'--print-cmake-dependencies',
default=False,
@ -326,32 +335,6 @@ def run_generator(generator):
outputs = _do_renders(renders, args.template_dir)
# The caller wants to assert that the outputs are only in specific
# directories.
if args.allowed_output_dirs_file != None:
with open(args.allowed_output_dirs_file) as f:
allowed_dirs = set([line.strip() for line in f.readlines()])
for directory in allowed_dirs:
if not directory.endswith('/'):
print('Allowed directory entry "{}" doesn\'t '
'end with /'.format(directory))
return 1
def check_in_subdirectory(path, directory):
return path.startswith(
directory) and not '/' in path[len(directory):]
for render in renders:
if not any(
check_in_subdirectory(render.output, directory)
for directory in allowed_dirs):
print('Output file "{}" is not in the allowed directory '
'list below:'.format(render.output))
for directory in sorted(allowed_dirs):
print(' "{}"'.format(directory))
return 1
# Output the JSON tarball
if args.output_json_tarball != None:
json_root = {}
@ -367,8 +350,7 @@ def run_generator(generator):
output_path = os.path.join(args.output_dir, output.name)
directory = os.path.dirname(output_path)
if not os.path.exists(directory):
os.makedirs(directory)
os.makedirs(directory, exist_ok=True)
with open(output_path, 'w') as outfile:
outfile.write(output.content)

View File

@ -1,91 +0,0 @@
#!/usr/bin/env python3
# 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.
import argparse, glob, os, sys
def check_in_subdirectory(path, directory):
return path.startswith(directory) and not '/' in path[len(directory):]
def check_is_allowed(path, allowed_dirs):
return any(
check_in_subdirectory(path, directory) for directory in allowed_dirs)
def get_all_files_in_dir(find_directory):
result = []
for (directory, _, files) in os.walk(find_directory):
result += [os.path.join(directory, filename) for filename in files]
return result
def run():
# Parse command line arguments
parser = argparse.ArgumentParser(
description="Removes stale autogenerated files from gen/ directories.")
parser.add_argument(
'--root-dir',
type=str,
help='The root directory, all other paths in files are relative to it.'
)
parser.add_argument(
'--allowed-output-dirs-file',
type=str,
help='The file containing a list of allowed directories')
parser.add_argument(
'--stale-dirs-file',
type=str,
help=
'The file containing a list of directories to check for stale files')
parser.add_argument('--stamp',
type=str,
help='A stamp written once this script completes')
args = parser.parse_args()
root_dir = args.root_dir
stamp_file = args.stamp
# Load the list of allowed and stale directories
with open(args.allowed_output_dirs_file) as f:
allowed_dirs = set(
[os.path.join(root_dir, line.strip()) for line in f.readlines()])
for directory in allowed_dirs:
if not directory.endswith('/'):
print('Allowed directory entry "{}" doesn\'t end with /'.format(
directory))
return 1
with open(args.stale_dirs_file) as f:
stale_dirs = set([line.strip() for line in f.readlines()])
# Remove all files in stale dirs that aren't in the allowed dirs.
for stale_dir in stale_dirs:
stale_dir = os.path.join(root_dir, stale_dir)
for candidate in get_all_files_in_dir(stale_dir):
if not check_is_allowed(candidate, allowed_dirs):
os.remove(candidate)
# Finished! Write the stamp file so ninja knows to not run this again.
with open(stamp_file, "w") as f:
f.write("")
return 0
if __name__ == "__main__":
sys.exit(run())

View File

@ -32,37 +32,58 @@
#ifndef {{metadata.api.upper()}}_H_
#define {{metadata.api.upper()}}_H_
{% set c_prefix = metadata.c_prefix %}
#if defined({{c_prefix}}_SHARED_LIBRARY)
{% set API = metadata.c_prefix %}
#if defined({{API}}_SHARED_LIBRARY)
# if defined(_WIN32)
# if defined({{c_prefix}}_IMPLEMENTATION)
# define {{c_prefix}}_EXPORT __declspec(dllexport)
# if defined({{API}}_IMPLEMENTATION)
# define {{API}}_EXPORT __declspec(dllexport)
# else
# define {{c_prefix}}_EXPORT __declspec(dllimport)
# define {{API}}_EXPORT __declspec(dllimport)
# endif
# else // defined(_WIN32)
# if defined({{c_prefix}}_IMPLEMENTATION)
# define {{c_prefix}}_EXPORT __attribute__((visibility("default")))
# if defined({{API}}_IMPLEMENTATION)
# define {{API}}_EXPORT __attribute__((visibility("default")))
# else
# define {{c_prefix}}_EXPORT
# define {{API}}_EXPORT
# endif
# endif // defined(_WIN32)
#else // defined({{c_prefix}}_SHARED_LIBRARY)
# define {{c_prefix}}_EXPORT
#endif // defined({{c_prefix}}_SHARED_LIBRARY)
#else // defined({{API}}_SHARED_LIBRARY)
# define {{API}}_EXPORT
#endif // defined({{API}}_SHARED_LIBRARY)
#if !defined({{API}}_OBJECT_ATTRIBUTE)
#define {{API}}_OBJECT_ATTRIBUTE
#endif
#if !defined({{API}}_ENUM_ATTRIBUTE)
#define {{API}}_ENUM_ATTRIBUTE
#endif
#if !defined({{API}}_STRUCTURE_ATTRIBUTE)
#define {{API}}_STRUCTURE_ATTRIBUTE
#endif
#if !defined({{API}}_FUNCTION_ATTRIBUTE)
#define {{API}}_FUNCTION_ATTRIBUTE
#endif
#if !defined({{API}}_NULLABLE)
#define {{API}}_NULLABLE
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
{% for constant in by_category["constant"] %}
#define {{c_prefix}}_{{constant.name.SNAKE_CASE()}} {{constant.value}}
#define {{API}}_{{constant.name.SNAKE_CASE()}} {{constant.value}}
{% endfor %}
typedef uint32_t {{c_prefix}}Flags;
typedef uint32_t {{API}}Flags;
{% for type in by_category["object"] %}
typedef struct {{as_cType(type.name)}}Impl* {{as_cType(type.name)}};
typedef struct {{as_cType(type.name)}}Impl* {{as_cType(type.name)}} {{API}}_OBJECT_ATTRIBUTE;
{% endfor %}
// Structure forward declarations
{% for type in by_category["structure"] %}
struct {{as_cType(type.name)}};
{% endfor %}
{% for type in by_category["enum"] + by_category["bitmask"] %}
@ -71,22 +92,34 @@ typedef uint32_t {{c_prefix}}Flags;
{{as_cEnum(type.name, value.name)}} = 0x{{format(value.value, "08X")}},
{% endfor %}
{{as_cEnum(type.name, Name("force32"))}} = 0x7FFFFFFF
} {{as_cType(type.name)}};
} {{as_cType(type.name)}} {{API}}_ENUM_ATTRIBUTE;
{% if type.category == "bitmask" %}
typedef {{c_prefix}}Flags {{as_cType(type.name)}}Flags;
typedef {{API}}Flags {{as_cType(type.name)}}Flags {{API}}_ENUM_ATTRIBUTE;
{% endif %}
{% endfor -%}
{% for type in by_category["function pointer"] %}
typedef {{as_cType(type.return_type.name)}} (*{{as_cType(type.name)}})(
{%- if type.arguments == [] -%}
void
{%- else -%}
{%- for arg in type.arguments -%}
{% if not loop.first %}, {% endif %}
{% if arg.type.category == "structure" %}struct {% endif %}{{as_annotated_cType(arg)}}
{%- endfor -%}
{%- endif -%}
) {{API}}_FUNCTION_ATTRIBUTE;
{% endfor %}
typedef struct {{c_prefix}}ChainedStruct {
struct {{c_prefix}}ChainedStruct const * next;
{{c_prefix}}SType sType;
} {{c_prefix}}ChainedStruct;
typedef struct {{API}}ChainedStruct {
struct {{API}}ChainedStruct const * next;
{{API}}SType sType;
} {{API}}ChainedStruct {{API}}_STRUCTURE_ATTRIBUTE;
typedef struct {{c_prefix}}ChainedStructOut {
struct {{c_prefix}}ChainedStructOut * next;
{{c_prefix}}SType sType;
} {{c_prefix}}ChainedStructOut;
typedef struct {{API}}ChainedStructOut {
struct {{API}}ChainedStructOut * next;
{{API}}SType sType;
} {{API}}ChainedStructOut {{API}}_STRUCTURE_ATTRIBUTE;
{% for type in by_category["structure"] %}
{% for root in type.chain_roots %}
@ -96,16 +129,19 @@ typedef struct {{c_prefix}}ChainedStructOut {
{% set Out = "Out" if type.output else "" %}
{% set const = "const " if not type.output else "" %}
{% if type.extensible %}
{{c_prefix}}ChainedStruct{{Out}} {{const}}* nextInChain;
{{API}}ChainedStruct{{Out}} {{const}}* nextInChain;
{% endif %}
{% if type.chained %}
{{c_prefix}}ChainedStruct{{Out}} chain;
{{API}}ChainedStruct{{Out}} chain;
{% endif %}
{% for member in type.members %}
{{as_annotated_cType(member)}};
{%- if member.optional %} // nullable{% endif %}{{""}}
{% if member.optional %}
{{API}}_NULLABLE {{as_annotated_cType(member)}};
{% else %}
{{as_annotated_cType(member)}};
{% endif-%}
{% endfor %}
} {{as_cType(type.name)}};
} {{as_cType(type.name)}} {{API}}_STRUCTURE_ATTRIBUTE;
{% endfor %}
{% for typeDef in by_category["typedef"] %}
@ -118,26 +154,14 @@ typedef struct {{c_prefix}}ChainedStructOut {
extern "C" {
#endif
{% for type in by_category["function pointer"] %}
typedef {{as_cType(type.return_type.name)}} (*{{as_cType(type.name)}})(
{%- if type.arguments == [] -%}
void
{%- else -%}
{%- for arg in type.arguments -%}
{% if not loop.first %}, {% endif %}{{as_annotated_cType(arg)}}
{%- endfor -%}
{%- endif -%}
);
{% endfor %}
#if !defined({{c_prefix}}_SKIP_PROCS)
#if !defined({{API}}_SKIP_PROCS)
{% for function in by_category["function"] %}
typedef {{as_cType(function.return_type.name)}} (*{{as_cProc(None, function.name)}})(
{%- for arg in function.arguments -%}
{% if not loop.first %}, {% endif %}{{as_annotated_cType(arg)}}
{%- endfor -%}
);
) {{API}}_FUNCTION_ATTRIBUTE;
{% endfor %}
{% for type in by_category["object"] if len(c_methods(type)) > 0 %}
@ -146,39 +170,41 @@ extern "C" {
typedef {{as_cType(method.return_type.name)}} (*{{as_cProc(type.name, method.name)}})(
{{-as_cType(type.name)}} {{as_varName(type.name)}}
{%- for arg in method.arguments -%}
, {{as_annotated_cType(arg)}}
{%- if arg.optional %} /* nullable */{% endif %}
,{{" "}}
{%- if arg.optional %}{{API}}_NULLABLE {% endif -%}
{{as_annotated_cType(arg)}}
{%- endfor -%}
);
) {{API}}_FUNCTION_ATTRIBUTE;
{% endfor %}
{% endfor %}
#endif // !defined({{c_prefix}}_SKIP_PROCS)
#endif // !defined({{API}}_SKIP_PROCS)
#if !defined({{c_prefix}}_SKIP_DECLARATIONS)
#if !defined({{API}}_SKIP_DECLARATIONS)
{% for function in by_category["function"] %}
{{c_prefix}}_EXPORT {{as_cType(function.return_type.name)}} {{as_cMethod(None, function.name)}}(
{{API}}_EXPORT {{as_cType(function.return_type.name)}} {{as_cMethod(None, function.name)}}(
{%- for arg in function.arguments -%}
{% if not loop.first %}, {% endif %}{{as_annotated_cType(arg)}}
{%- endfor -%}
);
) {{API}}_FUNCTION_ATTRIBUTE;
{% endfor %}
{% for type in by_category["object"] if len(c_methods(type)) > 0 %}
// Methods of {{type.name.CamelCase()}}
{% for method in c_methods(type) %}
{{c_prefix}}_EXPORT {{as_cType(method.return_type.name)}} {{as_cMethod(type.name, method.name)}}(
{{API}}_EXPORT {{as_cType(method.return_type.name)}} {{as_cMethod(type.name, method.name)}}(
{{-as_cType(type.name)}} {{as_varName(type.name)}}
{%- for arg in method.arguments -%}
, {{as_annotated_cType(arg)}}
{%- if arg.optional %} /* nullable */{% endif %}
,{{" "}}
{%- if arg.optional %}{{API}}_NULLABLE {% endif -%}
{{as_annotated_cType(arg)}}
{%- endfor -%}
);
) {{API}}_FUNCTION_ATTRIBUTE;
{% endfor %}
{% endfor %}
#endif // !defined({{c_prefix}}_SKIP_DECLARATIONS)
#endif // !defined({{API}}_SKIP_DECLARATIONS)
#ifdef __cplusplus
} // extern "C"

View File

@ -13,7 +13,7 @@
//* limitations under the License.
{% set API = metadata.api.upper() %}
{% set api = API.lower() %}
{% if 'dawn' not in enabled_tags %}
{% if 'dawn' in enabled_tags %}
#ifdef __EMSCRIPTEN__
#error "Do not include this header. Emscripten already provides headers needed for {{metadata.api}}."
#endif
@ -22,17 +22,14 @@
#define {{API}}_CPP_H_
#include "dawn/{{api}}.h"
#include "dawn/{{api}}_cpp_chained_struct.h"
#include "dawn/EnumClassBitmasks.h"
#include <cmath>
#include <cstddef>
#include <cstdint>
namespace {{metadata.namespace}} {
namespace detail {
constexpr size_t ConstexprMax(size_t a, size_t b) {
return a > b ? a : b;
}
} // namespace detail
{% set c_prefix = metadata.c_prefix %}
{% for constant in by_category["constant"] %}
{% set type = as_cppType(constant.type.name) %}
@ -136,11 +133,17 @@ namespace {{metadata.namespace}} {
CType Get() const {
return mHandle;
}
// TODO(dawn:1639) Deprecate Release after uses have been removed.
CType Release() {
CType result = mHandle;
mHandle = 0;
return result;
}
CType MoveToCHandle() {
CType result = mHandle;
mHandle = 0;
return result;
}
static Derived Acquire(CType handle) {
Derived result;
result.mHandle = handle;
@ -212,16 +215,6 @@ namespace {{metadata.namespace}} {
);
{% endfor %}
struct ChainedStruct {
ChainedStruct const * nextInChain = nullptr;
SType sType = SType::Invalid;
};
struct ChainedStructOut {
ChainedStruct * nextInChain = nullptr;
SType sType = SType::Invalid;
};
{% for type in by_category["structure"] %}
{% set Out = "Out" if type.output else "" %}
{% set const = "const" if not type.output else "" %}

View File

@ -0,0 +1,51 @@
//* Copyright 2023 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.
{% set API = metadata.api.upper() %}
{% if 'dawn' in enabled_tags %}
#ifdef __EMSCRIPTEN__
#error "Do not include this header. Emscripten already provides headers needed for {{metadata.api}}."
#endif
{% endif %}
#ifndef {{API}}_CPP_CHAINED_STRUCT_H_
#define {{API}}_CPP_CHAINED_STRUCT_H_
#include <cstddef>
#include <cstdint>
// This header file declares the ChainedStruct structures separately from the {{metadata.api}}
// headers so that dependencies can directly extend structures without including the larger header
// which exposes capabilities that may require correctly set proc tables.
namespace {{metadata.namespace}} {
namespace detail {
constexpr size_t ConstexprMax(size_t a, size_t b) {
return a > b ? a : b;
}
} // namespace detail
enum class SType : uint32_t;
struct ChainedStruct {
ChainedStruct const * nextInChain = nullptr;
SType sType = SType(0u);
};
struct ChainedStructOut {
ChainedStructOut * nextInChain = nullptr;
SType sType = SType(0u);
};
} // namespace {{metadata.namespace}}}
#endif // {{API}}_CPP_CHAINED_STRUCT_H_

View File

@ -21,7 +21,7 @@
#include "dawn/common/Assert.h"
namespace gpu_info {
namespace dawn::gpu_info {
namespace {
@ -151,4 +151,4 @@ std::string GetArchitectureName(PCIVendorID vendorId, PCIDeviceID deviceId) {
return "";
}
} // namespace gpu_info
} // namespace dawn::gpu_info

View File

@ -21,7 +21,7 @@
using PCIVendorID = uint32_t;
using PCIDeviceID = uint32_t;
namespace gpu_info {
namespace dawn::gpu_info {
// Vendor IDs
{% for vendor in vendors %}
@ -51,5 +51,5 @@ namespace gpu_info {
std::string GetVendorName(PCIVendorID vendorId);
std::string GetArchitectureName(PCIVendorID vendorId, PCIDeviceID deviceId);
} // namespace gpu_info
} // namespace dawn::gpu_info
#endif // SRC_DAWN_COMMON_GPUINFO_AUTOGEN_H_

View File

@ -0,0 +1,31 @@
// Copyright 2023 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.
#include <stdint.h>
namespace DawnLPMFuzzer {
static constexpr int kInstanceObjectId = 1;
static constexpr uint32_t kInvalidObjectId = {{ cmd_records["lpm_info"]["invalid object id"] }};
{% for type in by_category["object"] %}
{% if type.name.get() in cmd_records["lpm_info"]["limits"] %}
static constexpr int k{{ type.name.CamelCase() }}Limit = {{ cmd_records["lpm_info"]["limits"][type.name.get()] }};
{% else %}
static constexpr int k{{ type.name.CamelCase() }}Limit = {{ cmd_records["lpm_info"]["limits"]["default"] }};
{% endif %}
{% endfor %}
} // namespace DawnLPMFuzzer

View File

@ -0,0 +1,269 @@
// Copyright 2023 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.
#include "dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMFuzzer.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMObjectStore.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializerCustom.h"
#include "dawn/webgpu.h"
#include "dawn/wire/BufferConsumer_impl.h"
#include "dawn/wire/ObjectHandle.h"
#include "dawn/wire/Wire.h"
#include "dawn/wire/WireClient.h"
#include "dawn/wire/WireCmd_autogen.h"
#include "dawn/wire/WireResult.h"
#include "dawn/wire/client/ApiObjects_autogen.h"
namespace dawn::wire {
//* Outputs an rvalue that's the number of elements a pointer member points to.
{% macro member_length(member, proto_accessor) -%}
{%- if member.length == "constant" -%}
{{member.constant_length}}u
{%- else -%}
{{proto_accessor}}().size()
{%- endif -%}
{%- endmacro %}
//* Outputs the type that will be used on the wire for the member
{% macro member_type(member) -%}
{{ assert(as_cType(member.type.name) != "size_t") }}
{{as_cType(member.type.name)}}
{%- endmacro %}
//* Outputs the conversion code to put `in` in `out`
{% macro convert_member(member, in, out, in_access="") %}
{% if member.type in by_category["structure"] %}
{{ convert_structure(member, in, out, in_access) }}
{% elif member.type in by_category["bitmask"] %}
{{ convert_bitmask(member, in, out, in_access) }}
{% elif member.type in by_category["enum"] %}
{{ convert_enum(member, in, out, in_access) }}
{% elif member.type in by_category["object"] %}
{{ convert_object(member, in, out, in_access) }}
{% elif member.type.name.get() == "ObjectId" %}
{{ convert_objectid(member, in, out, access) }}
{% elif member.type.name.get() == "ObjectHandle" %}
{{ convert_objecthandle(member, in, out, in_access) }}
{% else %}
{{out}} = {{in}}({{in_access}});
{% endif %}
{% endmacro %}
//* Helper functions for converting protobufs to specific types
{% macro convert_enum(member, in, out, in_access) %}
{{out}} = static_cast<{{ member_type(member) }}>(
{{in}}({{in_access}})
);
{% endmacro %}
{% macro convert_object(member, in, out, in_access) -%}
{{ out }} = reinterpret_cast<{{ as_cType(member.type.name) }}>(
objectStores[ObjectType::{{ member.type.name.CamelCase() }}].Lookup(
static_cast<ObjectId>(
{{in}}({{in_access}})
)
)
);
{%- endmacro %}
{% macro convert_objectid(member, in, out, in_access) -%}
{{ out }} = objectStores[ObjectType::{{ member.id_type.name.CamelCase() }}].Lookup(
static_cast<ObjectId>(
{{in}}({{ in_access}})
)
);
{%- endmacro %}
{% macro convert_objecthandle(member, in, out, in_access) -%}
if (objectStores[ObjectType::{{ member.handle_type.name.CamelCase() }}].Size() < DawnLPMFuzzer::k{{ member.handle_type.name.CamelCase() }}Limit) {
{{ out }} = objectStores[ObjectType::{{ member.handle_type.name.CamelCase() }}].ReserveHandle();
} else {
{{ out }} = {0, 0};
}
{%- endmacro %}
{% macro convert_bitmask(member, in, out, in_access) -%}
{{ out }} = 0;
for (size_t bm = 0; bm < static_cast<size_t>({{ in }}().size()); bm++) {
{{ out }} |=
static_cast<{{ member_type(member) }}>(
{{ in }}(bm)
);
}
{%- endmacro %}
{% macro convert_structure(member, in, out, in_access) -%}
// Serializing a Structure Recursively
WIRE_TRY({{member_type(member)}}ProtoConvert({{in}}({{in_access}}), &{{out}}, serializeBuffer, objectStores));
{%- endmacro %}
{% macro write_record_conversion_helpers(record, name, members, is_cmd) %}
{% set overrides = cmd_records["lpm_info"]["overrides"] %}
{% set overrides_key = record.name.canonical_case() %}
{% set name = record.name.CamelCase() %}
{% set Cmd = "Cmd" if is_cmd else "" %}
{% set WGPU = "WGPU" if not is_cmd else "" %}
WireResult {{WGPU}}{{name}}ProtoConvert(fuzzing::{{ name }} proto_record, {{WGPU}}{{ name }}{{ Cmd }} const *record, SerializeBuffer* serializeBuffer, PerObjectType<DawnLPMObjectStore> &objectStores) {
{{WGPU}}{{ name }}{{ Cmd }} *mutable_record = const_cast<{{WGPU}}{{ name }}{{ Cmd }} *>(record);
//* Some commands don't set any members.
DAWN_UNUSED(mutable_record);
//* Zero out any non-serializable values as they won't be set
{% for member in members if member.skip_serialize %}
{% set memberName = as_varName(member.name) %}
memset(&mutable_record->{{ memberName }}, 0, sizeof(mutable_record->{{ memberName }}));
{% endfor %}
//* Pass by Value handling. This mirrors WireCmd with some differences between
//* convert_member and serialize_member
{% for member in members if member.annotation == "value" if not member.skip_serialize %}
{% set memberName = as_varName(member.name) %}
{% set protoMember = as_protobufMemberName(member.name) %}
//* Major WireCmd Divergence: Some member values are hardcoded in dawn_lpm.json
{% if overrides_key in overrides and member.name.canonical_case() in overrides[overrides_key] %}
mutable_record->{{ memberName }} = {{ overrides[overrides_key][member.name.canonical_case()] }};
{% else %}
{{ convert_member(member, 'proto_record.' + protoMember, "mutable_record->" + memberName) }}
{% endif %}
{% endfor %}
//* Chained structures are currently not supported.
{% if record.extensible %}
mutable_record->nextInChain = nullptr;
{% endif %}
//* Special handling for strings for now.
{% for member in members if member.length == "strlen" %}
{% set memberName = as_varName(member.name) %}
{
mutable_record->{{ memberName }} = "main";
}
{% endfor %}
//* Pass by Pointer handling. This mirrors WireCmd with some divergences when handling
//* byte arrays.
{% for member in members if member.annotation != "value" and member.length != "strlen" and not member.skip_serialize %}
{% set memberName = as_varName(member.name) %}
{% set protoMember = as_protobufMemberName(member.name) %}
{% set protoAccess = "i" if member.length != "constant" or member.constant_length > 1 else "" %}
//* Major WireCmd Divergence: DawnLPM handles raw byte arrays uniquely
//* as they don't lead to new coverage, lead to OOMs when allocated with
//* an arbitrary size, and are difficult to work with in protobuf.
{% if member.type.name.get() == 'uint8_t' %}
{
const size_t kDataBufferLength = 128;
auto memberLength = kDataBufferLength;
{{member_type(member)}}* memberBuffer;
WIRE_TRY(serializeBuffer->NextN(memberLength, &memberBuffer));
memset(memberBuffer, 0, kDataBufferLength);
mutable_record->{{ memberName }} = memberBuffer;
{% if member.length != "constant" -%}
mutable_record->{{ member.length.name.camelCase() }} = memberLength;
{%- endif %}
}
{% else %}
{
auto memberLength = static_cast<unsigned int>({{member_length(member, "proto_record." + protoMember)}});
//* Needed for the edge cases in "external texture descriptor"
//* where we want to fuzzer to fill the fixed-length float arrays
//* with values, but the length of the protobuf buffer might not
//* be large enough for "src transfer function parameters".
{% if member.length == "constant" and member.constant_length > 1 %}
memberLength = std::min(memberLength, static_cast<unsigned int>({{"proto_record." + protoMember}}().size()));
{% endif %}
{{member_type(member)}}* memberBuffer;
WIRE_TRY(serializeBuffer->NextN(memberLength, &memberBuffer));
for (decltype(memberLength) i = 0; i < memberLength; ++i) {
{{convert_member(member, "proto_record." + protoMember, "memberBuffer[i]", protoAccess )}}
}
mutable_record->{{ memberName }} = memberBuffer;
//* Major WireCmd Divergence: Within the serializer the length member is
//* set by using record.length. Here we aren't receiving any data
//* and set it to the number of protobuf objects in proto_record.
{% if member.length != "constant" -%}
mutable_record->{{ member.length.name.camelCase() }} = memberLength;
{%- endif %}
}
{% endif %}
{% endfor %}
return WireResult::Success;
}
{% endmacro %}
//* Output structure conversion first because it is used by commands.
{% for type in by_category["structure"] %}
{% set name = as_cType(type.name) %}
{% if type.name.CamelCase() not in client_side_structures %}
{{ write_record_conversion_helpers(type, name, type.members, False) }}
{% endif %}
{% endfor %}
//* Output command conversion functions.
{% for command in cmd_records["cpp_generated_commands"] %}
{% set name = command.name.CamelCase() %}
{{ write_record_conversion_helpers(command, name, command.members, True) }}
{% endfor %}
WireResult SerializedData(const fuzzing::Program& program, dawn::wire::ChunkedCommandSerializer serializer) {
DawnLPMObjectIdProvider provider;
PerObjectType<DawnLPMObjectStore> objectStores;
// Allocate a scoped buffer allocation
const size_t kMaxSerializeBufferSize = 65536;
std::unique_ptr<char[]> allocatedBuffer(
new char[kMaxSerializeBufferSize]()
);
for (const fuzzing::Command& command : program.commands()) {
switch (command.command_case()) {
{% for command in cmd_records["cpp_generated_commands"] %}
{% set name = command.name.CamelCase() %}
case fuzzing::Command::k{{name}}: {
SerializeBuffer serializeBuffer(allocatedBuffer.get(), kMaxSerializeBufferSize);
{{ name }}Cmd *cmd = nullptr;
WIRE_TRY(serializeBuffer.Next(&cmd));
WIRE_TRY({{name}}ProtoConvert(command.{{ command.name.concatcase() }}(), cmd, &serializeBuffer, objectStores));
serializer.SerializeCommand(*cmd, provider);
break;
}
{% endfor %}
default: {
GetCustomSerializedData(command, serializer, objectStores, provider);
break;
}
}
}
return WireResult::Success;
}
} // namespace dawn::wire

View File

@ -0,0 +1,47 @@
// Copyright 2023 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 SRC_DAWN_FUZZERS_DAWNLPMSERIALIZER_H_
#define SRC_DAWN_FUZZERS_DAWNLPMSERIALIZER_H_
#include "dawn/fuzzers/lpmfuzz/dawn_lpm_autogen.pb.h"
#include "dawn/wire/ChunkedCommandSerializer.h"
#include "dawn/wire/WireCmd_autogen.h"
#include "dawn/wire/WireResult.h"
namespace dawn::wire {
class DawnLPMObjectIdProvider : public ObjectIdProvider {
private:
// Implementation of the ObjectIdProvider interface
{% for type in by_category["object"] %}
WireResult GetId({{as_cType(type.name)}} object, ObjectId* out) const final {
*out = reinterpret_cast<uintptr_t>(object);
return WireResult::Success;
}
WireResult GetOptionalId({{as_cType(type.name)}} object, ObjectId* out) const final {
*out = reinterpret_cast<uintptr_t>(object);
return WireResult::Success;
}
{% endfor %}
};
WireResult SerializedData(const fuzzing::Program& program,
dawn::wire::ChunkedCommandSerializer serializer);
} // namespace dawn::wire
#endif // SRC_DAWN_FUZZERS_DAWNLPMSERIALIZER_H_

View File

@ -0,0 +1,179 @@
// Copyright 2023 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.
syntax = "proto2";
package fuzzing;
import "third_party/dawn/src/dawn/fuzzers/lpmfuzz/dawn_custom_lpm.proto";
// These are hardcoded limits for Dawn Object allocations based on type to help
// guide the fuzzer towards reusing existing objects.
{% for type in by_category["object"] %}
{% set type_key = type.name.canonical_case() %}
enum {{ type.name.CamelCase() }}Id {
{% if type_key in cmd_records["lpm_info"]["limits"] %}
{% for n in range(cmd_records["lpm_info"]["limits"][type_key]) %}
{{ type.name.SNAKE_CASE() }}_{{ loop.index }} = {{ loop.index }};
{% endfor %}
{% else %}
{% for n in range(cmd_records["lpm_info"]["limits"]["default"]) %}
{{ type.name.SNAKE_CASE() }}_{{ loop.index }} = {{ loop.index }};
{% endfor %}
{% endif %}
INVALID_{{ type.name.SNAKE_CASE() }} = {{ cmd_records["lpm_info"]["invalid object id"] }};
};
{% endfor %}
{% for type in by_category["enum"] %}
enum {{as_cppType(type.name)}} {
{% for value in type.values %}
{{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
{% endfor %}
};
{% endfor %}
{% for type in by_category["bitmask"] %}
enum {{as_cppType(type.name)}} {
{% for value in type.values %}
{{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
{% endfor %}
};
{% endfor %}
{% macro lift_string_proto_member(member, count) -%}
required string {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{%- endmacro %}
{% macro lift_float_array_proto_member(member, count) -%}
repeated float {{ as_varName(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{%- endmacro %}
{% macro lift_object_member(member, count) %}
{{ member.type.name.CamelCase() }}Id {{ as_protobufNameLPM(member.name) }}
{% endmacro %}
{% macro lift_objectid_member(member, count) %}
{{ member.id_type.name.CamelCase() }}Id {{ as_protobufNameLPM(member.name) }}
{% endmacro %}
{% macro lift_varlength_proto_member(member, count) -%}
{% if member.type in by_category["object"] %}
repeated {{ lift_object_member(member, count) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type.name.get() == "object id" %}
repeated {{ lift_objectid_member(member, count) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% else %}
repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% endif %}
{%- endmacro %}
{% macro lift_dawn_member_pass_by_value(record, name, member, count) %}
{% if member.type in by_category["structure"] %}
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type in by_category["bitmask"] %}
repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type in by_category["enum"] %}
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type in by_category["object"] %}
required {{ lift_object_member(member, count) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type.name.get() == "ObjectId" %}
required {{ lift_objectid_member(member, count) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type.name.get() == "ObjectHandle" %}
// Skips object handles while lifting dawn.json to protobuf because
// ObjectHandles are created and managed in DawnLPMSerializer. Passing
// arbitrary ObjectHandles from the fuzzer's bytestream isn't the
// strategy for this fuzzer.
{% else %}
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% endif %}
{% endmacro %}
{% macro lift_dawn_member_pass_by_pointer(record, name, member, count) %}
{% if member.type in by_category["structure"] and member.length == "constant" and member.constant_length == 1 %}
required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
{% set count.value = count.value + 1 %}
{% elif member.type.name.get() == "char" and member.length == 'strlen' %}
{{ lift_string_proto_member(member, count) }}
{% elif member.type.name.get() == "float" %}
{{ lift_float_array_proto_member(member, count) }}
{% elif member.type.name.get() == "uint8_t" %}
// Skip over byte arrays in protobuf, handled by DawnLPMSerializer
// with a hardcoded bytes and length.
{% elif member.length != 'constant' %}
{{ lift_varlength_proto_member(member, count) }}
{% else %}
// There shouldn't be any other pass-by-pointer types in
// dawn*.json, if any are added we would like to know at compile time
{{ unreachable_code() }}
{% endif %}
{% endmacro %}
{% macro lift_proto_members_helper(record, name, members) %}
{% set count = namespace(value=1) %}
{% for member in members %}
{% if member.skip_serialize == True %}
// {{ member.name.camelCase()}}.skip_serialize
{% elif member.annotation == 'value' %}
{{ lift_dawn_member_pass_by_value(record, name, member, count) }}
{% elif member.annotation == 'const*' %}
{{ lift_dawn_member_pass_by_pointer(record, name, member, count) }}
{% endif %}
{% endfor %}
{% endmacro %}
{% for structure in by_category["structure"] %}
message {{structure.name.CamelCase()}} {
{{ lift_proto_members_helper(structure, structure.name, structure.members) }}
}
{% endfor %}
{% for command in cmd_records["proto_generated_commands"] %}
message {{command.name.CamelCase()}} {
{{ lift_proto_members_helper(command, command.name, command.members) }}
}
{% endfor %}
message Command {
oneof command {
{% for command in cmd_records["proto_all_commands"] %}
{{command.name.CamelCase()}} {{command.name.camelCase()}} = {{ loop.index }};
{% endfor %}
}
}
message Program {
repeated Command commands = 1;
}

View File

@ -0,0 +1,22 @@
// Copyright 2023 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.
syntax = "proto2";
package fuzzing;
enum ObjectType {
{% for type in by_category["object"] %}
{{ type.name.CamelCase() }} = {{ loop.index - 1}};
{% endfor %}
};

View File

@ -23,43 +23,55 @@
namespace {{native_namespace}} {
{% set namespace = metadata.namespace %}
{% for value in types["s type"].values %}
{% if value.valid %}
void FindInChain(const ChainedStruct* chain, const {{as_cppEnum(value.name)}}** out) {
for (; chain; chain = chain->nextInChain) {
if (chain->sType == {{namespace}}::SType::{{as_cppEnum(value.name)}}) {
*out = static_cast<const {{as_cppEnum(value.name)}}*>(chain);
break;
}
}
}
{% endif %}
{% endfor %}
MaybeError ValidateSTypes(const ChainedStruct* chain,
std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints) {
std::unordered_set<{{namespace}}::SType> allSTypes;
for (; chain; chain = chain->nextInChain) {
if (allSTypes.find(chain->sType) != allSTypes.end()) {
return DAWN_VALIDATION_ERROR("Chain cannot have duplicate sTypes");
}
DAWN_INVALID_IF(allSTypes.find(chain->sType) != allSTypes.end(),
"Extension chain has duplicate sType %s.", chain->sType);
allSTypes.insert(chain->sType);
}
for (const auto& oneOfConstraint : oneOfConstraints) {
bool satisfied = false;
for ({{namespace}}::SType oneOfSType : oneOfConstraint) {
if (allSTypes.find(oneOfSType) != allSTypes.end()) {
if (satisfied) {
return DAWN_VALIDATION_ERROR("Unsupported sType combination");
}
DAWN_INVALID_IF(satisfied,
"sType %s is part of a group of exclusive sTypes that is already present.",
oneOfSType);
satisfied = true;
allSTypes.erase(oneOfSType);
}
}
}
if (!allSTypes.empty()) {
return DAWN_VALIDATION_ERROR("Unsupported sType");
DAWN_INVALID_IF(!allSTypes.empty(), "Unsupported sType %s.", *allSTypes.begin());
return {};
}
MaybeError ValidateSTypes(const ChainedStructOut* chain,
std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints) {
std::unordered_set<{{namespace}}::SType> allSTypes;
for (; chain; chain = chain->nextInChain) {
DAWN_INVALID_IF(allSTypes.find(chain->sType) != allSTypes.end(),
"Extension chain has duplicate sType %s.", chain->sType);
allSTypes.insert(chain->sType);
}
for (const auto& oneOfConstraint : oneOfConstraints) {
bool satisfied = false;
for ({{namespace}}::SType oneOfSType : oneOfConstraint) {
if (allSTypes.find(oneOfSType) != allSTypes.end()) {
DAWN_INVALID_IF(satisfied,
"sType %s is part of a group of exclusive sTypes that is already present.",
oneOfSType);
satisfied = true;
allSTypes.erase(oneOfSType);
}
}
}
DAWN_INVALID_IF(!allSTypes.empty(), "Unsupported sType %s.", *allSTypes.begin());
return {};
}

View File

@ -18,6 +18,7 @@
#define {{DIR}}_CHAIN_UTILS_H_
{% set impl_dir = metadata.impl_dir + "/" if metadata.impl_dir else "" %}
{% set namespace = metadata.namespace %}
{% set namespace_name = Name(metadata.native_namespace) %}
{% set native_namespace = namespace_name.namespace_case() %}
{% set native_dir = impl_dir + namespace_name.Dirs() %}
@ -26,11 +27,44 @@
#include "{{native_dir}}/Error.h"
namespace {{native_namespace}} {
namespace detail {
// Mapping from native types to the expected STypes is implemented as template specializations.
template <typename T>
struct STypeForImpl;
{% for value in types["s type"].values %}
{% if value.valid %}
void FindInChain(const ChainedStruct* chain, const {{as_cppEnum(value.name)}}** out);
{% if value.valid and value.name.get() in types %}
template <>
struct STypeForImpl<{{as_cppEnum(value.name)}}> {
static constexpr {{namespace}}::SType value = {{namespace}}::SType::{{as_cppEnum(value.name)}};
};
{% endif %}
{% endfor %}
template <>
struct STypeForImpl<DawnInstanceDescriptor> {
static constexpr {{namespace}}::SType value = {{namespace}}::SType::DawnInstanceDescriptor;
};
} // namespace detail
template <typename T>
constexpr {{namespace}}::SType STypeFor = detail::STypeForImpl<T>::value;
template <typename T>
void FindInChain(const ChainedStruct* chain, const T** out) {
for (; chain; chain = chain->nextInChain) {
if (chain->sType == STypeFor<T>) {
*out = static_cast<const T*>(chain);
break;
}
}
}
template <typename T>
void FindInChain(ChainedStructOut* chain, T** out) {
for (; chain; chain = chain->nextInChain) {
if (chain->sType == STypeFor<T>) {
*out = static_cast<T*>(chain);
break;
}
}
}
// Verifies that |chain| only contains ChainedStructs of types enumerated in
// |oneOfConstraints| and contains no duplicate sTypes. Each vector in
@ -38,9 +72,10 @@ namespace {{native_namespace}} {
// For example:
// ValidateSTypes(chain, { { ShaderModuleSPIRVDescriptor, ShaderModuleWGSLDescriptor } }))
// ValidateSTypes(chain, { { Extension1 }, { Extension2 } })
{% set namespace = metadata.namespace %}
MaybeError ValidateSTypes(const ChainedStruct* chain,
std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints);
MaybeError ValidateSTypes(const ChainedStructOut* chain,
std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints);
template <typename T>
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType) {
@ -48,6 +83,12 @@ namespace {{native_namespace}} {
"Unsupported sType (%s). Expected (%s)", chain->sType, sType);
return {};
}
template <typename T>
MaybeError ValidateSingleSTypeInner(const ChainedStructOut* chain, T sType) {
DAWN_INVALID_IF(chain->sType != sType,
"Unsupported sType (%s). Expected (%s)", chain->sType, sType);
return {};
}
template <typename T, typename... Args>
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType, Args... sTypes) {
@ -56,6 +97,13 @@ namespace {{native_namespace}} {
}
return ValidateSingleSTypeInner(chain, sTypes...);
}
template <typename T, typename... Args>
MaybeError ValidateSingleSTypeInner(const ChainedStructOut* chain, T sType, Args... sTypes) {
if (chain->sType == sType) {
return {};
}
return ValidateSingleSTypeInner(chain, sTypes...);
}
// Verifies that |chain| contains a single ChainedStruct of type |sType| or no ChainedStructs
// at all.
@ -68,6 +116,15 @@ namespace {{native_namespace}} {
"Chain can only contain a single chained struct.");
return ValidateSingleSTypeInner(chain, sType);
}
template <typename T>
MaybeError ValidateSingleSType(const ChainedStructOut* chain, T sType) {
if (chain == nullptr) {
return {};
}
DAWN_INVALID_IF(chain->nextInChain != nullptr,
"Chain can only contain a single chained struct.");
return ValidateSingleSTypeInner(chain, sType);
}
// Verifies that |chain| contains a single ChainedStruct with a type enumerated in the
// parameter pack or no ChainedStructs at all.
@ -80,6 +137,15 @@ namespace {{native_namespace}} {
"Chain can only contain a single chained struct.");
return ValidateSingleSTypeInner(chain, sType, sTypes...);
}
template <typename T, typename... Args>
MaybeError ValidateSingleSType(const ChainedStructOut* chain, T sType, Args... sTypes) {
if (chain == nullptr) {
return {};
}
DAWN_INVALID_IF(chain->nextInChain != nullptr,
"Chain can only contain a single chained struct.");
return ValidateSingleSTypeInner(chain, sType, sTypes...);
}
} // namespace {{native_namespace}}

View File

@ -56,6 +56,17 @@ namespace {{native_namespace}} {
{% endif %}
{%- endfor-%}
{% if method.autolock %}
{% if type.name.get() != "device" %}
auto device = self->GetDevice();
{% else %}
auto device = self;
{% endif %}
auto deviceLock(device->GetScopedLock());
{% else %}
// This method is specified to not use AutoLock in json script.
{% endif %}
{% if method.return_type.name.canonical_case() != "void" %}
auto result =
{%- endif %}

View File

@ -29,7 +29,7 @@ namespace {{native_namespace}} {
return {};
{% endfor %}
default:
return DAWN_VALIDATION_ERROR("Invalid value for {{as_cType(type.name)}}");
return DAWN_VALIDATION_ERROR("Value %i is invalid for {{as_cType(type.name)}}.", static_cast<uint32_t>(value));
}
}
@ -40,7 +40,7 @@ namespace {{native_namespace}} {
if ((value & static_cast<{{namespace}}::{{as_cppType(type.name)}}>(~{{type.full_mask}})) == 0) {
return {};
}
return DAWN_VALIDATION_ERROR("Invalid value for {{as_cType(type.name)}}");
return DAWN_VALIDATION_ERROR("Value %i is invalid for {{as_cType(type.name)}}.", static_cast<uint32_t>(value));
}
{% endfor %}

View File

@ -25,7 +25,15 @@
namespace {{native_namespace}} {
//
// Cache key writers for wgpu structures used in caching.
// Streaming readers for wgpu structures.
//
{% macro render_reader(member) %}
{%- set name = member.name.camelCase() -%}
DAWN_TRY(StreamOut(source, &t->{{name}}));
{% endmacro %}
//
// Streaming writers for wgpu structures.
//
{% macro render_writer(member) %}
{%- set name = member.name.camelCase() -%}
@ -38,31 +46,50 @@ namespace {{native_namespace}} {
{% endif %}
{% endmacro %}
{# Helper macro to render writers. Should be used in a call block to provide additional custom
{# Helper macro to render readers and writers. Should be used in a call block to provide additional custom
handling when necessary. The optional `omit` field can be used to omit fields that are either
handled in the custom code, or unnecessary in the serialized output.
Example:
{% call render_cache_key_writer("struct name", omits=["omit field"]) %}
{% call render_streaming_impl("struct name", writer=true, reader=false, omits=["omit field"]) %}
// Custom C++ code to handle special types/members that are hard to generate code for
{% endcall %}
One day we should probably make the generator smart enough to generate everything it can
instead of manually adding streaming implementations here.
#}
{% macro render_cache_key_writer(json_type, omits=[]) %}
{% macro render_streaming_impl(json_type, writer, reader, omits=[]) %}
{%- set cpp_type = types[json_type].name.CamelCase() -%}
template <>
void stream::Stream<{{cpp_type}}>::Write(stream::Sink* sink, const {{cpp_type}}& t) {
{{ caller() }}
{% for member in types[json_type].members %}
{%- if not member.name.get() in omits %}
{{render_writer(member)}}
{%- endif %}
{% endfor %}
}
{% if reader %}
template <>
MaybeError stream::Stream<{{cpp_type}}>::Read(stream::Source* source, {{cpp_type}}* t) {
{{ caller() }}
{% for member in types[json_type].members %}
{% if not member.name.get() in omits %}
{{render_reader(member)}}
{% endif %}
{% endfor %}
return {};
}
{% endif %}
{% if writer %}
template <>
void stream::Stream<{{cpp_type}}>::Write(stream::Sink* sink, const {{cpp_type}}& t) {
{{ caller() }}
{% for member in types[json_type].members %}
{% if not member.name.get() in omits %}
{{render_writer(member)}}
{% endif %}
{% endfor %}
}
{% endif %}
{% endmacro %}
{% call render_cache_key_writer("adapter properties") %}
{% call render_streaming_impl("adapter properties", true, false) %}
{% endcall %}
{% call render_cache_key_writer("dawn cache device descriptor") %}
{% call render_streaming_impl("dawn cache device descriptor", true, false) %}
{% endcall %}
{% call render_streaming_impl("extent 3D", true, true) %}
{% endcall %}
} // namespace {{native_namespace}}

View File

@ -44,14 +44,13 @@ namespace {{native_namespace}} {
{%- endif -%}
{%- endmacro %}
struct ChainedStruct {
ChainedStruct const * nextInChain = nullptr;
{{namespace}}::SType sType = {{namespace}}::SType::Invalid;
};
using {{namespace}}::ChainedStruct;
using {{namespace}}::ChainedStructOut;
{% for type in by_category["structure"] %}
{% if type.chained %}
struct {{as_cppType(type.name)}} : ChainedStruct {
{% set chainedStructType = "ChainedStructOut" if type.chained == "out" else "ChainedStruct" %}
struct {{as_cppType(type.name)}} : {{chainedStructType}} {
{{as_cppType(type.name)}}() {
sType = {{namespace}}::SType::{{type.name.CamelCase()}};
}
@ -59,7 +58,8 @@ namespace {{native_namespace}} {
struct {{as_cppType(type.name)}} {
{% endif %}
{% if type.extensible %}
ChainedStruct const * nextInChain = nullptr;
{% set chainedStructType = "ChainedStructOut" if type.output else "ChainedStruct const" %}
{{chainedStructType}} * nextInChain = nullptr;
{% endif %}
{% for member in type.members %}
{% set member_declaration = as_annotated_frontendType(member) + render_cpp_default_value(member) %}

View File

@ -48,6 +48,23 @@ namespace {{native_namespace}} {
inline {{as_cppType(type.name)}}* FromAPI({{as_cType(type.name)}}* rhs) {
return reinterpret_cast<{{as_cppType(type.name)}}*>(rhs);
}
inline const {{metadata.namespace}}::{{as_cppType(type.name)}}* ToCppAPI(const {{as_cppType(type.name)}}* rhs) {
return reinterpret_cast<const {{metadata.namespace}}::{{as_cppType(type.name)}}*>(rhs);
}
inline {{metadata.namespace}}::{{as_cppType(type.name)}}* ToCppAPI({{as_cppType(type.name)}}* rhs) {
return reinterpret_cast<{{metadata.namespace}}::{{as_cppType(type.name)}}*>(rhs);
}
inline const {{as_cppType(type.name)}}* FromCppAPI(const {{metadata.namespace}}::{{as_cppType(type.name)}}* rhs) {
return reinterpret_cast<const {{as_cppType(type.name)}}*>(rhs);
}
inline {{as_cppType(type.name)}}* FromCppAPI({{metadata.namespace}}::{{as_cppType(type.name)}}* rhs) {
return reinterpret_cast<{{as_cppType(type.name)}}*>(rhs);
}
{% endfor %}
{% for type in by_category["object"] %}
@ -87,6 +104,6 @@ namespace {{native_namespace}} {
return static_cast<{{namespace}}::{{as_cppType(type.name)}}>(rhs);
}
{% endfor %}
}
} // namespace {{native_namespace}}
#endif // {{NATIVE_DIR}}_{{PREFIX}}_PLATFORM_AUTOGEN_H_

View File

@ -19,6 +19,8 @@
namespace dawn::wire {
constexpr uint32_t kObjectTypes = {{len(by_category["object"])}};
enum class ObjectType : uint32_t {
{% for type in by_category["object"] %}
{{type.name.CamelCase()}},

View File

@ -64,13 +64,10 @@
{%- set Optional = "Optional" if member.optional else "" -%}
WIRE_TRY(provider.Get{{Optional}}Id({{in}}, &{{out}}));
{%- elif member.type.category == "structure" -%}
{%- if member.type.is_wire_transparent -%}
static_assert(sizeof({{out}}) == sizeof({{in}}), "Serialize memcpy size must match.");
memcpy(&{{out}}, &{{in}}, {{member_transfer_sizeof(member)}});
{%- else -%}
{%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%}
WIRE_TRY({{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}}));
{%- endif -%}
//* Do not memcpy or we may serialize padding bytes which can leak information across a
//* trusted boundary.
{%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%}
WIRE_TRY({{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}}));
{%- else -%}
{{out}} = {{in}};
{%- endif -%}
@ -166,9 +163,11 @@
{% if member.optional %}
bool has_{{memberName}} = record.{{memberName}} != nullptr;
if (has_{{memberName}})
{% else %}
ASSERT(record.{{memberName}} != nullptr);
{% endif %}
{
result += std::strlen(record.{{memberName}});
result += Align(std::strlen(record.{{memberName}}), kWireBufferAlignment);
}
{% endfor %}
@ -181,7 +180,9 @@
{% if member.annotation != "value" %}
{{ assert(member.annotation != "const*const*") }}
auto memberLength = {{member_length(member, "record.")}};
result += memberLength * {{member_transfer_sizeof(member)}};
auto size = WireAlignSizeofN<{{member_transfer_type(member)}}>(memberLength);
ASSERT(size);
result += *size;
//* Structures might contain more pointers so we need to add their extra size as well.
{% if member.type.category == "structure" %}
for (decltype(memberLength) i = 0; i < memberLength; ++i) {
@ -434,7 +435,7 @@
{% set Cmd = Name + "Cmd" %}
size_t {{Cmd}}::GetRequiredSize() const {
size_t size = sizeof({{Name}}Transfer) + {{Name}}GetExtraRequiredSize(*this);
size_t size = WireAlignSizeof<{{Name}}Transfer>() + {{Name}}GetExtraRequiredSize(*this);
return size;
}
@ -512,7 +513,7 @@
) %}
case {{as_cEnum(types["s type"].name, sType.name)}}: {
const auto& typedStruct = *reinterpret_cast<{{as_cType(sType.name)}} const *>(chainedStruct);
result += sizeof({{as_cType(sType.name)}}Transfer);
result += WireAlignSizeof<{{as_cType(sType.name)}}Transfer>();
result += {{as_cType(sType.name)}}GetExtraRequiredSize(typedStruct);
chainedStruct = typedStruct.chain.next;
break;
@ -522,7 +523,7 @@
case WGPUSType_Invalid:
default:
// Invalid enum. Reserve space just for the transfer header (sType and hasNext).
result += sizeof(WGPUChainedStructTransfer);
result += WireAlignSizeof<WGPUChainedStructTransfer>();
chainedStruct = chainedStruct->next;
break;
}
@ -603,7 +604,7 @@
WIRE_TRY(deserializeBuffer->Read(&transfer));
{{CType}}* outStruct;
WIRE_TRY(GetSpace(allocator, sizeof({{CType}}), &outStruct));
WIRE_TRY(GetSpace(allocator, 1u, &outStruct));
outStruct->chain.sType = sType;
outStruct->chain.next = nullptr;
@ -632,7 +633,7 @@
WIRE_TRY(deserializeBuffer->Read(&transfer));
{{ChainedStruct}}* outStruct;
WIRE_TRY(GetSpace(allocator, sizeof({{ChainedStruct}}), &outStruct));
WIRE_TRY(GetSpace(allocator, 1u, &outStruct));
outStruct->sType = WGPUSType_Invalid;
outStruct->next = nullptr;
@ -657,13 +658,23 @@ namespace dawn::wire {
// Always writes to |out| on success.
template <typename T, typename N>
WireResult GetSpace(DeserializeAllocator* allocator, N count, T** out) {
constexpr size_t kMaxCountWithoutOverflows = std::numeric_limits<size_t>::max() / sizeof(T);
if (count > kMaxCountWithoutOverflows) {
// Because we use this function extensively when `count` == 1, we can optimize the
// size computations a bit more for those cases via constexpr version of the
// alignment computation.
constexpr size_t kSizeofT = WireAlignSizeof<T>();
size_t size = 0;
if (count == 1) {
size = kSizeofT;
} else {
auto sizeN = WireAlignSizeofN<T>(count);
// A size of 0 indicates an overflow, so return an error.
if (!sizeN) {
return WireResult::FatalError;
}
size = *sizeN;
}
size_t totalSize = sizeof(T) * count;
*out = static_cast<T*>(allocator->GetSpace(totalSize));
*out = static_cast<T*>(allocator->GetSpace(size));
if (*out == nullptr) {
return WireResult::FatalError;
}

View File

@ -47,7 +47,7 @@ namespace dawn::wire::server {
{% set Type = member.handle_type.name.CamelCase() %}
{% set name = as_varName(member.name) %}
auto* {{name}}Data = {{Type}}Objects().Allocate(cmd.{{name}}.id);
auto* {{name}}Data = {{Type}}Objects().Allocate(cmd.{{name}});
if ({{name}}Data == nullptr) {
return false;
}

View File

@ -36,13 +36,26 @@ MaybeError OpenGLFunctionsBase::LoadOpenGLESProcs(GetProcAddress getProc, int ma
{% endfor %}
InitializeSupportedGLExtensions();
{% for block in extension_gles_blocks %}
// {{block.extension}}
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
if (IsGLExtensionSupported("{{block.extension}}")) {
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
{% endfor %}
}
{% endfor %}
// GL_ANGLE_base_vertex_base_instance
// See crbug.com/dawn/1715 for why this is embedded
if (IsGLExtensionSupported("GL_ANGLE_base_vertex_base_instance")) {
DAWN_TRY(LoadProc(getProc, &DrawArraysInstancedBaseInstanceANGLE, "glDrawArraysInstancedBaseInstanceANGLE"));
DAWN_TRY(LoadProc(getProc, &DrawElementsInstancedBaseVertexBaseInstanceANGLE, "glDrawElementsInstancedBaseVertexBaseInstanceANGLE"));
DAWN_TRY(LoadProc(getProc, &MultiDrawArraysInstancedBaseInstanceANGLE, "glMultiDrawArraysInstancedBaseInstanceANGLE"));
DAWN_TRY(LoadProc(getProc, &MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE, "glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE"));
}
return {};
}
@ -57,14 +70,33 @@ MaybeError OpenGLFunctionsBase::LoadDesktopGLProcs(GetProcAddress getProc, int m
{% endfor %}
InitializeSupportedGLExtensions();
{% for block in extension_desktop_gl_blocks %}
// {{block.extension}}
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
{% endfor %}
if (IsGLExtensionSupported("{{block.extension}}")) {
{% for proc in block.procs %}
DAWN_TRY(LoadProc(getProc, &{{proc.ProcName()}}, "{{proc.glProcName()}}"));
{% endfor %}
}
{% endfor %}
return {};
}
void OpenGLFunctionsBase::InitializeSupportedGLExtensions() {
int32_t numExtensions;
GetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
for (int32_t i = 0; i < numExtensions; ++i) {
const char* extensionName = reinterpret_cast<const char*>(GetStringi(GL_EXTENSIONS, i));
mSupportedGLExtensionsSet.insert(extensionName);
}
}
bool OpenGLFunctionsBase::IsGLExtensionSupported(const char* extension) const {
ASSERT(extension != nullptr);
return mSupportedGLExtensionsSet.count(extension) != 0;
}
} // namespace dawn::native::opengl

View File

@ -15,6 +15,8 @@
#ifndef DAWNNATIVE_OPENGL_OPENGLFUNCTIONSBASE_H_
#define DAWNNATIVE_OPENGL_OPENGLFUNCTIONSBASE_H_
#include <unordered_set>
#include "dawn/native/Error.h"
#include "dawn/native/opengl/opengl_platform.h"
@ -31,6 +33,15 @@ namespace dawn::native::opengl {
{% endfor%}
// GL_ANGLE_base_vertex_base_instance
// See crbug.com/dawn/1715 for why this is embedded
PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC DrawArraysInstancedBaseInstanceANGLE = nullptr;
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC DrawElementsInstancedBaseVertexBaseInstanceANGLE = nullptr;
PFNGLMULTIDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC MultiDrawArraysInstancedBaseInstanceANGLE = nullptr;
PFNGLMULTIDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC MultiDrawElementsInstancedBaseVertexBaseInstanceANGLE = nullptr;
bool IsGLExtensionSupported(const char* extension) const;
protected:
MaybeError LoadDesktopGLProcs(GetProcAddress getProc, int majorVersion, int minorVersion);
MaybeError LoadOpenGLESProcs(GetProcAddress getProc, int majorVersion, int minorVersion);
@ -38,6 +49,9 @@ namespace dawn::native::opengl {
private:
template<typename T>
MaybeError LoadProc(GetProcAddress getProc, T* memberProc, const char* name);
void InitializeSupportedGLExtensions();
std::unordered_set<std::string> mSupportedGLExtensionsSet;
};
} // namespace dawn::native::opengl

View File

@ -70,4 +70,12 @@ using GLDEBUGPROCAMD = void(KHRONOS_APIENTRY*)(GLuint id,
{% endfor %}
{% endfor%}
// GL_ANGLE_base_vertex_base_instance
// See crbug.com/dawn/1715 for why this is embedded
using PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount, GLuint baseInstance);
using PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices, GLsizei instanceCount, GLint baseVertex, GLuint baseInstance);
using PFNGLMULTIDRAWARRAYSINSTANCEDBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, const GLint * firsts, const GLsizei * counts, const GLsizei * instanceCounts, const GLuint * baseInstances, GLsizei drawcount);
using PFNGLMULTIDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEANGLEPROC = void(KHRONOS_APIENTRY *)(GLenum mode, const GLsizei * counts, GLenum type, const GLvoid *const* indices, const GLsizei * instanceCounts, const GLint * baseVertices, const GLuint * baseInstances, GLsizei drawcount);
#undef DAWN_GL_APIENTRY

53
go.mod
View File

@ -3,46 +3,53 @@ module dawn.googlesource.com/dawn
go 1.18
require (
github.com/andygrunwald/go-gerrit v0.0.0-20220427111355-d3e91fbf2db5
github.com/andygrunwald/go-gerrit v0.0.0-20230508072829-423d372345aa
github.com/ben-clayton/webidlparser v0.0.0-20210923100217-8ba896ded094
github.com/fatih/color v1.13.0
github.com/google/go-cmp v0.5.6
github.com/mattn/go-colorable v0.1.9
github.com/mattn/go-isatty v0.0.14
github.com/sergi/go-diff v1.2.0
github.com/google/go-cmp v0.5.9
github.com/mattn/go-colorable v0.1.12
github.com/mattn/go-isatty v0.0.16
github.com/sergi/go-diff v1.3.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/tidwall/jsonc v0.3.2
go.chromium.org/luci v0.0.0-20220412023008-ab2409fe739a
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
google.golang.org/api v0.63.0
google.golang.org/protobuf v1.28.0
go.chromium.org/luci v0.0.0-20230311013728-313c8e2205bc
golang.org/x/net v0.8.0
golang.org/x/oauth2 v0.6.0
google.golang.org/api v0.112.0
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.29.0
)
require (
cloud.google.com/go v0.99.0 // indirect
cloud.google.com/go/compute v1.18.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.1 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/klauspost/compress v1.13.5 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/maruel/subcommands v1.1.0 // indirect
github.com/maruel/subcommands v1.1.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/texttheater/golang-levenshtein v1.0.1 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.23.0 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8 // indirect
google.golang.org/grpc v1.44.0 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/appengine v1.6.8-0.20221117013220-504804fb50de // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
)
exclude github.com/sergi/go-diff v1.2.0

871
go.sum

File diff suppressed because it is too large Load Diff

35
go_presubmit_support.py Normal file
View File

@ -0,0 +1,35 @@
# Copyright 2022 The Dawn & Tint 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.
def go_path(input_api):
go = input_api.os_path.join(input_api.change.RepositoryRoot(), "tools",
"golang", "bin", "go")
if input_api.is_windows:
go += '.exe'
return go
def RunGoTests(input_api, output_api):
results = []
try:
input_api.subprocess.check_call_out(
[go_path(input_api), "test", "./..."],
stdout=input_api.subprocess.PIPE,
stderr=input_api.subprocess.PIPE,
cwd=input_api.PresubmitLocalPath())
except input_api.subprocess.CalledProcessError as e:
results.append(output_api.PresubmitError('%s' % (e, )))
return results

View File

@ -34,7 +34,6 @@ source_set("headers") {
public_deps = [ ":headers_gen" ]
sources = get_target_outputs(":headers_gen")
sources += [ "${dawn_root}/include/dawn/dawn_wsi.h" ]
}
###############################################################################
@ -45,6 +44,7 @@ dawn_json_generator("cpp_headers_gen") {
target = "cpp_headers"
outputs = [
"include/dawn/webgpu_cpp.h",
"include/dawn/webgpu_cpp_chained_struct.h",
"include/dawn/webgpu_cpp_print.h",
]
}

View File

@ -53,7 +53,7 @@ struct BoolConvertible {
using Integral = typename std::underlying_type<T>::type;
// NOLINTNEXTLINE(runtime/explicit)
constexpr BoolConvertible(Integral value) : value(value) {}
explicit constexpr BoolConvertible(Integral value) : value(value) {}
constexpr operator bool() const { return value != 0; }
constexpr operator T() const { return static_cast<T>(value); }
@ -74,8 +74,8 @@ template <
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator|(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) |
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) |
static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
}
template <
@ -85,8 +85,8 @@ template <
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator&(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) &
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) &
static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
}
template <
@ -96,15 +96,15 @@ template <
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator^(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
return BoolConvertible<T>(static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^
static_cast<Integral>(LowerBitmask<T2>::Lower(right)));
}
template <typename T1>
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator~(T1 t) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return ~static_cast<Integral>(LowerBitmask<T1>::Lower(t));
return BoolConvertible<T>(~static_cast<Integral>(LowerBitmask<T1>::Lower(t)));
}
template <

View File

@ -1,87 +0,0 @@
// Copyright 2017 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 INCLUDE_DAWN_DAWN_WSI_H_
#define INCLUDE_DAWN_DAWN_WSI_H_
#include "dawn/webgpu.h"
// Error message (or nullptr if there was no error)
typedef const char* DawnSwapChainError;
constexpr DawnSwapChainError DAWN_SWAP_CHAIN_NO_ERROR = nullptr;
constexpr DawnSwapChainError DAWN_SWAP_CHAIN_ERROR_OUT_OF_DATE = "Out of date";
typedef struct {
/// Backend-specific texture id/name/pointer
union {
void* ptr;
uint64_t u64;
uint32_t u32;
} texture;
} DawnSwapChainNextTexture;
typedef struct {
/// Initialize the swap chain implementation.
/// (*wsiContext) is one of DawnWSIContext{D3D12,Metal,GL}
void (*Init)(void* userData, void* wsiContext);
/// Destroy the swap chain implementation.
void (*Destroy)(void* userData);
/// Configure/reconfigure the swap chain.
DawnSwapChainError (*Configure)(void* userData,
WGPUTextureFormat format,
WGPUTextureUsage allowedUsage,
uint32_t width,
uint32_t height);
/// Acquire the next texture from the swap chain.
DawnSwapChainError (*GetNextTexture)(void* userData, DawnSwapChainNextTexture* nextTexture);
/// Present the last acquired texture to the screen.
DawnSwapChainError (*Present)(void* userData);
/// Each function is called with userData as its first argument.
void* userData;
/// For use by the D3D12 and Vulkan backends: how the swapchain will use the texture.
WGPUTextureUsage textureUsage;
} DawnSwapChainImplementation;
#if defined(DAWN_ENABLE_BACKEND_D3D12) && defined(__cplusplus)
struct DawnWSIContextD3D12 {
WGPUDevice device = nullptr;
};
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL) && defined(__OBJC__)
#import <Metal/Metal.h>
struct DawnWSIContextMetal {
id<MTLDevice> device = nil;
id<MTLCommandQueue> queue = nil;
};
#endif
#ifdef DAWN_ENABLE_BACKEND_OPENGL
typedef struct {
} DawnWSIContextGL;
#endif
#ifdef DAWN_ENABLE_BACKEND_VULKAN
typedef struct {
} DawnWSIContextVulkan;
#endif
#endif // INCLUDE_DAWN_DAWN_WSI_H_

View File

@ -0,0 +1,41 @@
// Copyright 2023 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 INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_
#define INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_
#include <d3d11_1.h>
#include <windows.h>
#include <wrl/client.h>
#include <memory>
#include "dawn/native/D3DBackend.h"
namespace dawn::native::d3d11 {
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public d3d::PhysicalDeviceDiscoveryOptions {
PhysicalDeviceDiscoveryOptions();
explicit PhysicalDeviceDiscoveryOptions(Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr<ID3D11Device> GetD3D11Device(WGPUDevice device);
} // namespace dawn::native::d3d11
#endif // INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_

View File

@ -20,25 +20,14 @@
#include <windows.h>
#include <wrl/client.h>
#include <memory>
#include "dawn/dawn_wsi.h"
#include "dawn/native/DawnNative.h"
#include "dawn/native/D3DBackend.h"
struct ID3D12Device;
struct ID3D12Resource;
namespace dawn::native::d3d12 {
class D3D11on12ResourceCache;
class Device;
class ExternalImageDXGIImpl;
DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device);
DAWN_NATIVE_EXPORT DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device,
HWND window);
DAWN_NATIVE_EXPORT WGPUTextureFormat
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
enum MemorySegment {
Local,
@ -49,80 +38,14 @@ DAWN_NATIVE_EXPORT uint64_t SetExternalMemoryReservation(WGPUDevice device,
uint64_t requestedReservationSize,
MemorySegment memorySegment);
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorDXGISharedHandle : ExternalImageDescriptor {
public:
ExternalImageDescriptorDXGISharedHandle();
// Note: SharedHandle must be a handle to a texture object.
// TODO(dawn:576): Remove after changing Chromium code to set textureSharedHandle.
HANDLE sharedHandle = nullptr;
HANDLE textureSharedHandle = nullptr;
// Optional shared handle to a D3D11/12 fence which can be used to synchronize using wait/signal
// values specified in the access descriptor below. If null, the texture will be assumed to have
// an associated DXGI keyed mutex which will be used with a fixed key of 0 for synchronization.
HANDLE fenceSharedHandle = nullptr;
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public d3d::PhysicalDeviceDiscoveryOptions {
PhysicalDeviceDiscoveryOptions();
explicit PhysicalDeviceDiscoveryOptions(Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
};
// Keyed mutex acquire/release uses a fixed key of 0 to match Chromium behavior.
constexpr UINT64 kDXGIKeyedMutexAcquireReleaseKey = 0;
struct DAWN_NATIVE_EXPORT ExternalImageAccessDescriptorDXGISharedHandle
: ExternalImageAccessDescriptor {
public:
// Value used for fence wait. A value of 0 is valid, but essentially a no-op since the fence
// lifetime starts with the 0 value signaled. A value of UINT64_MAX is ignored since it's also
// used by the D3D runtime to indicate that the device was removed.
uint64_t fenceWaitValue = 0;
// Value to signal the fence with after the texture is destroyed. A value of 0 means the fence
// will not be signaled.
uint64_t fenceSignalValue = 0;
// Whether the texture is for a WebGPU swap chain.
bool isSwapChainTexture = false;
};
// TODO(dawn:576): Remove after changing Chromium code to use the new struct name.
struct DAWN_NATIVE_EXPORT ExternalImageAccessDescriptorDXGIKeyedMutex
: ExternalImageAccessDescriptorDXGISharedHandle {
public:
// TODO(chromium:1241533): Remove deprecated keyed mutex params after removing associated
// code from Chromium - we use a fixed key of 0 for acquire and release everywhere now.
uint64_t acquireMutexKey;
uint64_t releaseMutexKey;
};
class DAWN_NATIVE_EXPORT ExternalImageDXGI {
public:
~ExternalImageDXGI();
static std::unique_ptr<ExternalImageDXGI> Create(
WGPUDevice device,
const ExternalImageDescriptorDXGISharedHandle* descriptor);
// Returns true if the external image resources are still valid, otherwise ProduceTexture() is
// guaranteed to fail e.g. after device destruction.
bool IsValid() const;
// TODO(sunnyps): |device| is ignored - remove after Chromium migrates to single parameter call.
WGPUTexture ProduceTexture(WGPUDevice device,
const ExternalImageAccessDescriptorDXGISharedHandle* descriptor);
WGPUTexture ProduceTexture(const ExternalImageAccessDescriptorDXGISharedHandle* descriptor);
private:
explicit ExternalImageDXGI(std::unique_ptr<ExternalImageDXGIImpl> impl);
std::unique_ptr<ExternalImageDXGIImpl> mImpl;
};
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
AdapterDiscoveryOptions();
explicit AdapterDiscoveryOptions(Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
} // namespace dawn::native::d3d12

View File

@ -0,0 +1,101 @@
// Copyright 2023 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 INCLUDE_DAWN_NATIVE_D3DBACKEND_H_
#define INCLUDE_DAWN_NATIVE_D3DBACKEND_H_
#include <dxgi1_4.h>
#include <windows.h>
#include <wrl/client.h>
#include <memory>
#include <vector>
#include "dawn/native/DawnNative.h"
namespace dawn::native::d3d {
class ExternalImageDXGIImpl;
DAWN_NATIVE_EXPORT Microsoft::WRL::ComPtr<IDXGIAdapter> GetDXGIAdapter(WGPUAdapter adapter);
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public PhysicalDeviceDiscoveryOptionsBase {
PhysicalDeviceDiscoveryOptions(WGPUBackendType type,
Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorDXGISharedHandle : ExternalImageDescriptor {
public:
ExternalImageDescriptorDXGISharedHandle();
// Note: SharedHandle must be a handle to a texture object.
HANDLE sharedHandle = nullptr;
};
struct DAWN_NATIVE_EXPORT ExternalImageDXGIFenceDescriptor {
// Shared handle for the fence. This never passes ownership to the callee (when used as an input
// parameter) or to the caller (when used as a return value or output parameter).
HANDLE fenceHandle = nullptr;
// The value that was previously signaled on this fence and should be waited on.
uint64_t fenceValue = 0;
};
struct DAWN_NATIVE_EXPORT ExternalImageDXGIBeginAccessDescriptor {
bool isInitialized = false; // Whether the texture is initialized on import
WGPUTextureUsageFlags usage = WGPUTextureUsage_None;
// A list of fences to wait on before accessing the texture.
std::vector<ExternalImageDXGIFenceDescriptor> waitFences;
// Whether the texture is for a WebGPU swap chain.
bool isSwapChainTexture = false;
};
class DAWN_NATIVE_EXPORT ExternalImageDXGI {
public:
~ExternalImageDXGI();
static std::unique_ptr<ExternalImageDXGI> Create(
WGPUDevice device,
const ExternalImageDescriptorDXGISharedHandle* descriptor);
// Returns true if the external image resources are still valid, otherwise BeginAccess() is
// guaranteed to fail e.g. after device destruction.
bool IsValid() const;
// Creates WGPUTexture wrapping the DXGI shared handle. The provided wait fences will be
// synchronized before using the texture in any command lists. Empty fences (nullptr handle) are
// ignored for convenience (EndAccess can return such fences).
WGPUTexture BeginAccess(const ExternalImageDXGIBeginAccessDescriptor* descriptor);
// Returns the signalFence that the client must wait on for correct synchronization. Can return
// an empty fence (nullptr handle) if the texture wasn't accessed by Dawn.
// Note that merely calling Destroy() on the WGPUTexture does not ensure synchronization.
void EndAccess(WGPUTexture texture, ExternalImageDXGIFenceDescriptor* signalFence);
private:
explicit ExternalImageDXGI(std::unique_ptr<ExternalImageDXGIImpl> impl);
std::unique_ptr<ExternalImageDXGIImpl> mImpl;
};
} // namespace dawn::native::d3d
#endif // INCLUDE_DAWN_NATIVE_D3DBACKEND_H_

View File

@ -21,6 +21,7 @@
#include "dawn/dawn_proc_table.h"
#include "dawn/native/dawn_native_export.h"
#include "dawn/webgpu.h"
#include "dawn/webgpu_cpp_chained_struct.h"
namespace dawn::platform {
class Platform;
@ -36,18 +37,9 @@ namespace dawn::native {
class InstanceBase;
class AdapterBase;
// 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.
struct DAWN_NATIVE_EXPORT DawnDeviceDescriptor {
DawnDeviceDescriptor();
~DawnDeviceDescriptor();
std::vector<const char*> requiredFeatures;
std::vector<const char*> forceEnabledToggles;
std::vector<const char*> forceDisabledToggles;
const WGPURequiredLimits* requiredLimits = nullptr;
};
// Each toggle is assigned with a TogglesStage, indicating the validation and earliest usage
// time of the toggle.
enum class ToggleStage { Instance, Adapter, Device };
// A struct to record the information of a toggle. A toggle is a code path in Dawn device that
// can be manually configured to run or not outside Dawn, including workarounds, special
@ -56,12 +48,21 @@ struct ToggleInfo {
const char* name;
const char* description;
const char* url;
ToggleStage stage;
};
// A struct to record the information of a feature. A feature is a GPU feature that is not
// required to be supported by all Dawn backends and can only be used when it is enabled on the
// creation of device.
using FeatureInfo = ToggleInfo;
struct FeatureInfo {
const char* name;
const char* description;
const char* url;
// The enum of feature state, could be stable or experimental. Using an experimental feature
// requires the AllowUnsafeAPIs toggle to be enabled.
enum class FeatureState { Stable = 0, Experimental };
FeatureState featureState;
};
// 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
@ -97,13 +98,9 @@ class DAWN_NATIVE_EXPORT Adapter {
explicit operator bool() const;
// Create a device on this adapter. On an error, nullptr is returned.
WGPUDevice CreateDevice(const DawnDeviceDescriptor* deviceDescriptor);
WGPUDevice CreateDevice(const wgpu::DeviceDescriptor* deviceDescriptor);
WGPUDevice CreateDevice(const WGPUDeviceDescriptor* deviceDescriptor = nullptr);
void RequestDevice(const DawnDeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);
void RequestDevice(const wgpu::DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata);
@ -121,17 +118,35 @@ class DAWN_NATIVE_EXPORT Adapter {
AdapterBase* mImpl = nullptr;
};
// Base class for options passed to Instance::DiscoverAdapters.
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptionsBase {
// Base class for options passed to Instance::DiscoverPhysicalDevices.
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptionsBase {
public:
const WGPUBackendType backendType;
protected:
explicit AdapterDiscoveryOptionsBase(WGPUBackendType type);
explicit PhysicalDeviceDiscoveryOptionsBase(WGPUBackendType type);
};
// Deprecated, use PhysicalDeviceDiscoveryOptionsBase instead.
// TODO(dawn:1774): Remove this.
using AdapterDiscoveryOptionsBase = PhysicalDeviceDiscoveryOptionsBase;
enum BackendValidationLevel { Full, Partial, Disabled };
// Can be chained in InstanceDescriptor
struct DAWN_NATIVE_EXPORT DawnInstanceDescriptor : wgpu::ChainedStruct {
DawnInstanceDescriptor();
static constexpr size_t kFirstMemberAlignment =
wgpu::detail::ConstexprMax(alignof(wgpu::ChainedStruct), alignof(uint32_t));
alignas(kFirstMemberAlignment) uint32_t additionalRuntimeSearchPathsCount = 0;
const char* const* additionalRuntimeSearchPaths;
dawn::platform::Platform* platform = nullptr;
// Equality operators, mostly for testing. Note that this tests
// strict pointer-pointer equality if the struct contains member pointers.
bool operator==(const DawnInstanceDescriptor& rhs) const;
};
// Represents a connection to dawn_native and is used for dependency injection, discovering
// system adapters and injecting custom adapters (like a Swiftshader Vulkan adapter).
//
@ -145,15 +160,20 @@ class DAWN_NATIVE_EXPORT Instance {
Instance(const Instance& other) = delete;
Instance& operator=(const Instance& other) = delete;
// Gather all adapters in the system that can be accessed with no special options. These
// adapters will later be returned by GetAdapters.
void DiscoverDefaultAdapters();
// Gather all physical devices in the system that can be accessed with no special options.
void DiscoverDefaultPhysicalDevices();
// Adds adapters that can be discovered with the options provided (like a getProcAddress).
// The backend is chosen based on the type of the options used. Returns true on success.
// Adds physical devices that can be discovered with the options provided (like a
// getProcAddress). The backend is chosen based on the type of the options used. Returns true on
// success.
bool DiscoverPhysicalDevices(const PhysicalDeviceDiscoveryOptionsBase* options);
// Deprecated, use DiscoverDefaultPhysicalDevices and DiscoverPhysicalDevices instead.
// TODO(Dawn:1774): Remove these.
void DiscoverDefaultAdapters();
bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options);
// Returns all the adapters that the instance knows about.
// Returns a vector of adapters, one for each physical device the instance knows about.
std::vector<Adapter> GetAdapters() const;
const ToggleInfo* GetToggleInfo(const char* toggleName);
@ -166,8 +186,8 @@ class DAWN_NATIVE_EXPORT Instance {
// Enable debug capture on Dawn startup
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
// TODO(dawn:1374) Deprecate this once it is passed via the descriptor.
void SetPlatform(dawn::platform::Platform* platform);
// Enable / disable the adapter blocklist.
void EnableAdapterBlocklist(bool enable);
uint64_t GetDeviceCountForTesting() const;
@ -207,6 +227,8 @@ DAWN_NATIVE_EXPORT std::vector<const char*> GetProcMapNamesForTesting();
DAWN_NATIVE_EXPORT bool DeviceTick(WGPUDevice device);
DAWN_NATIVE_EXPORT bool InstanceProcessEvents(WGPUInstance instance);
// ErrorInjector functions used for testing only. Defined in dawn_native/ErrorInjector.cpp
DAWN_NATIVE_EXPORT void EnableErrorInjector();
DAWN_NATIVE_EXPORT void DisableErrorInjector();
@ -221,6 +243,7 @@ enum ExternalImageType {
IOSurface,
DXGISharedHandle,
EGLImage,
AHardwareBuffer,
};
// Common properties of external images
@ -237,12 +260,6 @@ struct DAWN_NATIVE_EXPORT ExternalImageDescriptor {
ExternalImageType mType;
};
struct DAWN_NATIVE_EXPORT ExternalImageAccessDescriptor {
public:
bool isInitialized = false; // Whether the texture is initialized on import
WGPUTextureUsageFlags usage = WGPUTextureUsage_None;
};
struct DAWN_NATIVE_EXPORT ExternalImageExportInfo {
public:
bool isInitialized = false; // Whether the texture is initialized after export
@ -266,6 +283,12 @@ DAWN_NATIVE_EXPORT bool BindGroupLayoutBindingsEqualForTesting(WGPUBindGroupLayo
} // namespace dawn::native
// Alias the DawnInstanceDescriptor up to wgpu.
// TODO(dawn:1374) Remove this aliasing once the usages are updated.
namespace wgpu {
using dawn::native::DawnInstanceDescriptor;
} // namespace wgpu
// TODO(dawn:824): Remove once the deprecation period is passed.
namespace dawn_native = dawn::native;

View File

@ -15,7 +15,8 @@
#ifndef INCLUDE_DAWN_NATIVE_METALBACKEND_H_
#define INCLUDE_DAWN_NATIVE_METALBACKEND_H_
#include "dawn/dawn_wsi.h"
#include <vector>
#include "dawn/native/DawnNative.h"
// The specifics of the Metal backend expose types in function signatures that might not be
@ -34,23 +35,52 @@ typedef __IOSurface* IOSurfaceRef;
namespace dawn::native::metal {
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
AdapterDiscoveryOptions();
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public PhysicalDeviceDiscoveryOptionsBase {
PhysicalDeviceDiscoveryOptions();
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
struct DAWN_NATIVE_EXPORT ExternalImageMTLSharedEventDescriptor {
// Shared event handle `id<MTLSharedEvent>`.
// This never passes ownership to the callee (when used as an input
// parameter) or to the caller (when used as a return value or output parameter).
#ifdef __OBJC__
id<MTLSharedEvent> sharedEvent = nil;
static_assert(sizeof(id<MTLSharedEvent>) == sizeof(void*));
static_assert(alignof(id<MTLSharedEvent>) == alignof(void*));
#else
void* sharedEvent = nullptr;
#endif
// The value that was previously signaled on this event and should be waited on.
uint64_t signaledValue = 0;
};
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorIOSurface : ExternalImageDescriptor {
public:
ExternalImageDescriptorIOSurface();
~ExternalImageDescriptorIOSurface();
IOSurfaceRef ioSurface;
// This has been deprecated.
uint32_t plane;
// A list of events to wait on before accessing the texture.
std::vector<ExternalImageMTLSharedEventDescriptor> waitEvents;
};
struct DAWN_NATIVE_EXPORT ExternalImageIOSurfaceEndAccessDescriptor
: ExternalImageMTLSharedEventDescriptor {
bool isInitialized;
};
DAWN_NATIVE_EXPORT WGPUTexture WrapIOSurface(WGPUDevice device,
const ExternalImageDescriptorIOSurface* descriptor);
DAWN_NATIVE_EXPORT void IOSurfaceEndAccess(WGPUTexture texture,
ExternalImageIOSurfaceEndAccessDescriptor* descriptor);
// When making Metal interop with other APIs, we need to be careful that QueueSubmit doesn't
// mean that the operations will be visible to other APIs/Metal devices right away. macOS
// does have a global queue of graphics operations, but the command buffers are inserted there

View File

@ -15,11 +15,12 @@
#ifndef INCLUDE_DAWN_NATIVE_NULLBACKEND_H_
#define INCLUDE_DAWN_NATIVE_NULLBACKEND_H_
#include "dawn/dawn_wsi.h"
#include "dawn/native/DawnNative.h"
namespace dawn::native::null {
DAWN_NATIVE_EXPORT DawnSwapChainImplementation CreateNativeSwapChainImpl();
// Nothing for now \o/
} // namespace dawn::native::null
#endif // INCLUDE_DAWN_NATIVE_NULLBACKEND_H_

View File

@ -17,13 +17,13 @@
typedef void* EGLImage;
#include "dawn/dawn_wsi.h"
#include "dawn/native/DawnNative.h"
namespace dawn::native::opengl {
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
explicit AdapterDiscoveryOptions(WGPUBackendType type);
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public PhysicalDeviceDiscoveryOptionsBase {
explicit PhysicalDeviceDiscoveryOptions(WGPUBackendType type);
void* (*getProc)(const char*);
// Context
@ -32,18 +32,14 @@ struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptio
void* userData;
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
// TODO(crbug.com/dawn/810): This struct can be removed once Chrome is no longer using it.
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptionsES : public AdapterDiscoveryOptions {
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptionsES : public PhysicalDeviceDiscoveryOptions {
AdapterDiscoveryOptionsES();
};
using PresentCallback = void (*)(void*);
DAWN_NATIVE_EXPORT DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device,
PresentCallback present,
void* presentUserdata);
DAWN_NATIVE_EXPORT WGPUTextureFormat
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorEGLImage : ExternalImageDescriptor {
public:
ExternalImageDescriptorEGLImage();

View File

@ -20,7 +20,6 @@
#include <array>
#include <vector>
#include "dawn/dawn_wsi.h"
#include "dawn/native/DawnNative.h"
namespace dawn::native::vulkan {
@ -29,17 +28,23 @@ DAWN_NATIVE_EXPORT VkInstance GetInstance(WGPUDevice device);
DAWN_NATIVE_EXPORT PFN_vkVoidFunction GetInstanceProcAddr(WGPUDevice device, const char* pName);
DAWN_NATIVE_EXPORT DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device,
::VkSurfaceKHR surface);
DAWN_NATIVE_EXPORT WGPUTextureFormat
GetNativeSwapChainPreferredFormat(const DawnSwapChainImplementation* swapChain);
struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
AdapterDiscoveryOptions();
struct DAWN_NATIVE_EXPORT PhysicalDeviceDiscoveryOptions
: public PhysicalDeviceDiscoveryOptionsBase {
PhysicalDeviceDiscoveryOptions();
bool forceSwiftShader = false;
};
// TODO(dawn:1774): Deprecated.
using AdapterDiscoveryOptions = PhysicalDeviceDiscoveryOptions;
enum class NeedsDedicatedAllocation {
Yes,
No,
// Use Vulkan reflection to detect whether a dedicated allocation is needed.
Detect,
};
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorVk : ExternalImageDescriptor {
public:
// The following members may be ignored if |ExternalImageDescriptor::isInitialized| is false
@ -54,6 +59,11 @@ struct DAWN_NATIVE_EXPORT ExternalImageDescriptorVk : ExternalImageDescriptor {
VkImageLayout releasedOldLayout = VK_IMAGE_LAYOUT_GENERAL;
VkImageLayout releasedNewLayout = VK_IMAGE_LAYOUT_GENERAL;
// Try to detect the need to use a dedicated allocation for imported images by default but let
// the application override this as drivers have bugs and forget to require a dedicated
// allocation.
NeedsDedicatedAllocation dedicatedAllocation = NeedsDedicatedAllocation::Detect;
protected:
using ExternalImageDescriptor::ExternalImageDescriptor;
};
@ -126,6 +136,26 @@ struct DAWN_NATIVE_EXPORT ExternalImageExportInfoDmaBuf : ExternalImageExportInf
ExternalImageExportInfoDmaBuf();
};
#ifdef __ANDROID__
// Descriptor for AHardwareBuffer image import
struct DAWN_NATIVE_EXPORT ExternalImageDescriptorAHardwareBuffer : ExternalImageDescriptorVk {
public:
ExternalImageDescriptorAHardwareBuffer();
struct AHardwareBuffer* handle; // The AHardwareBuffer which contains the memory of the image
std::vector<int> waitFDs; // File descriptors of semaphores which will be waited on
protected:
using ExternalImageDescriptorVk::ExternalImageDescriptorVk;
};
struct DAWN_NATIVE_EXPORT ExternalImageExportInfoAHardwareBuffer : ExternalImageExportInfoFD {
ExternalImageExportInfoAHardwareBuffer();
};
#endif // __ANDROID__
#endif // __linux__
// Imports external memory into a Vulkan image. Internally, this uses external memory /
@ -142,6 +172,8 @@ DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice device,
DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture,
VkImageLayout desiredLayout,
ExternalImageExportInfoVk* info);
// |ExportVulkanImage| with default desiredLayout of VK_IMAGE_LAYOUT_UNDEFINED.
DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture, ExternalImageExportInfoVk* info);
} // namespace dawn::native::vulkan

View File

@ -70,9 +70,9 @@ class DAWN_WIRE_EXPORT WireClient : public CommandHandler {
const volatile char* HandleCommands(const volatile char* commands, size_t size) override;
ReservedTexture ReserveTexture(WGPUDevice device,
const WGPUTextureDescriptor* descriptor);
ReservedSwapChain ReserveSwapChain(WGPUDevice device);
ReservedTexture ReserveTexture(WGPUDevice device, const WGPUTextureDescriptor* descriptor);
ReservedSwapChain ReserveSwapChain(WGPUDevice device,
const WGPUSwapChainDescriptor* descriptor);
ReservedDevice ReserveDevice();
ReservedInstance ReserveInstance();

View File

@ -16,12 +16,18 @@
#define SRC_TINT_OVERRIDE_ID_H_
#include <stdint.h>
#include <functional>
#include "src/tint/reflection.h"
namespace tint {
/// OverrideId is a numerical identifier for an override variable, unique per program.
struct OverrideId {
uint16_t value = 0;
/// Reflect the fields of this struct so that it can be used by tint::ForeachField()
TINT_REFLECT(value);
};
/// Equality operator for OverrideId

View File

@ -15,24 +15,27 @@
#ifndef INCLUDE_TINT_TINT_H_
#define INCLUDE_TINT_TINT_H_
// Guard for accidental includes to private headers
#define CURRENTLY_IN_TINT_PUBLIC_HEADER
// TODO(tint:88): When implementing support for an install target, all of these
// headers will need to be moved to include/tint/.
#include "src/tint/demangler.h"
#include "src/tint/ast/transform/first_index_offset.h"
#include "src/tint/ast/transform/renamer.h"
#include "src/tint/ast/transform/single_entry_point.h"
#include "src/tint/ast/transform/substitute_override.h"
#include "src/tint/ast/transform/vertex_pulling.h"
#include "src/tint/diagnostic/printer.h"
#include "src/tint/inspector/inspector.h"
#include "src/tint/reader/reader.h"
#include "src/tint/sem/type_manager.h"
#include "src/tint/transform/binding_remapper.h"
#include "src/tint/transform/first_index_offset.h"
#include "src/tint/transform/fold_trivial_single_use_lets.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/renamer.h"
#include "src/tint/transform/robustness.h"
#include "src/tint/transform/single_entry_point.h"
#include "src/tint/transform/substitute_override.h"
#include "src/tint/transform/vertex_pulling.h"
#include "src/tint/type/manager.h"
#include "src/tint/utils/unicode.h"
#include "src/tint/writer/array_length_from_uniform_options.h"
#include "src/tint/writer/binding_point.h"
#include "src/tint/writer/binding_remapper_options.h"
#include "src/tint/writer/external_texture_options.h"
#include "src/tint/writer/flatten_bindings.h"
#include "src/tint/writer/writer.h"
@ -45,7 +48,6 @@
#endif // TINT_BUILD_WGSL_READER
#if TINT_BUILD_SPV_WRITER
#include "spirv-tools/libspirv.hpp"
#include "src/tint/writer/spirv/generator.h"
#endif // TINT_BUILD_SPV_WRITER
@ -65,4 +67,16 @@
#include "src/tint/writer/glsl/generator.h"
#endif // TINT_BUILD_GLSL_WRITER
namespace tint {
/// Initialize initializes the Tint library. Call before using the Tint API.
void Initialize();
/// Shutdown uninitializes the Tint library. Call after using the Tint API.
void Shutdown();
} // namespace tint
#undef CURRENTLY_IN_TINT_PUBLIC_HEADER
#endif // INCLUDE_TINT_TINT_H_

View File

@ -18,6 +18,9 @@ config_groups {
projects {
name: "dawn"
ref_regexp: "refs/heads/.+"
ref_regexp_exclude: "refs/heads/chromium/5615"
ref_regexp_exclude: "refs/heads/chromium/5672"
ref_regexp_exclude: "refs/heads/chromium/5735"
}
}
verifiers {
@ -26,6 +29,12 @@ config_groups {
dry_run_access_list: "project-dawn-tryjob-access"
}
tryjob {
builders {
name: "chromium/try/android-dawn-arm-rel"
}
builders {
name: "chromium/try/android-dawn-arm64-rel"
}
builders {
name: "chromium/try/dawn-try-win10-x86-rel"
includable_only: true
@ -89,3 +98,243 @@ config_groups {
}
}
}
config_groups {
name: "Dawn-CQ-m112"
gerrit {
url: "https://dawn-review.googlesource.com"
projects {
name: "dawn"
ref_regexp: "refs/heads/chromium/5615"
}
}
verifiers {
gerrit_cq_ability {
committer_list: "project-dawn-committers"
dry_run_access_list: "project-dawn-tryjob-access"
}
tryjob {
builders {
name: "chromium-m112/try/dawn-android-arm-deps-rel"
}
builders {
name: "chromium-m112/try/dawn-mac-x64-deps-rel"
}
builders {
name: "chromium-m112/try/dawn-win10-x64-deps-rel"
}
builders {
name: "chromium-m112/try/dawn-win10-x86-deps-rel"
includable_only: true
}
builders {
name: "dawn/try/linux-clang-dbg-x64"
}
builders {
name: "dawn/try/linux-clang-dbg-x86"
}
builders {
name: "dawn/try/linux-clang-rel-x64"
}
builders {
name: "dawn/try/linux-clang-rel-x86"
}
builders {
name: "dawn/try/mac-dbg"
}
builders {
name: "dawn/try/mac-rel"
}
builders {
name: "dawn/try/presubmit"
disable_reuse: true
}
builders {
name: "dawn/try/win-clang-dbg-x64"
}
builders {
name: "dawn/try/win-clang-dbg-x86"
}
builders {
name: "dawn/try/win-clang-rel-x64"
}
builders {
name: "dawn/try/win-clang-rel-x86"
}
builders {
name: "dawn/try/win-msvc-dbg-x64"
}
builders {
name: "dawn/try/win-msvc-rel-x64"
}
retry_config {
single_quota: 1
global_quota: 2
failure_weight: 1
transient_failure_weight: 1
timeout_weight: 2
}
}
}
}
config_groups {
name: "Dawn-CQ-m113"
gerrit {
url: "https://dawn-review.googlesource.com"
projects {
name: "dawn"
ref_regexp: "refs/heads/chromium/5672"
}
}
verifiers {
gerrit_cq_ability {
committer_list: "project-dawn-committers"
dry_run_access_list: "project-dawn-tryjob-access"
}
tryjob {
builders {
name: "chromium-m113/try/dawn-android-arm-deps-rel"
}
builders {
name: "chromium-m113/try/dawn-linux-x64-deps-rel"
}
builders {
name: "chromium-m113/try/dawn-mac-x64-deps-rel"
}
builders {
name: "chromium-m113/try/dawn-win10-x64-deps-rel"
}
builders {
name: "chromium-m113/try/dawn-win10-x86-deps-rel"
includable_only: true
}
builders {
name: "dawn/try/linux-clang-dbg-x64"
}
builders {
name: "dawn/try/linux-clang-dbg-x86"
}
builders {
name: "dawn/try/linux-clang-rel-x64"
}
builders {
name: "dawn/try/linux-clang-rel-x86"
}
builders {
name: "dawn/try/mac-dbg"
}
builders {
name: "dawn/try/mac-rel"
}
builders {
name: "dawn/try/presubmit"
disable_reuse: true
}
builders {
name: "dawn/try/win-clang-dbg-x64"
}
builders {
name: "dawn/try/win-clang-dbg-x86"
}
builders {
name: "dawn/try/win-clang-rel-x64"
}
builders {
name: "dawn/try/win-clang-rel-x86"
}
builders {
name: "dawn/try/win-msvc-dbg-x64"
}
builders {
name: "dawn/try/win-msvc-rel-x64"
}
retry_config {
single_quota: 1
global_quota: 2
failure_weight: 1
transient_failure_weight: 1
timeout_weight: 2
}
}
}
}
config_groups {
name: "Dawn-CQ-m114"
gerrit {
url: "https://dawn-review.googlesource.com"
projects {
name: "dawn"
ref_regexp: "refs/heads/chromium/5735"
}
}
verifiers {
gerrit_cq_ability {
committer_list: "project-dawn-committers"
dry_run_access_list: "project-dawn-tryjob-access"
}
tryjob {
builders {
name: "chromium-m114/try/dawn-android-arm-deps-rel"
}
builders {
name: "chromium-m114/try/dawn-linux-x64-deps-rel"
}
builders {
name: "chromium-m114/try/dawn-mac-x64-deps-rel"
}
builders {
name: "chromium-m114/try/dawn-win10-x64-deps-rel"
}
builders {
name: "chromium-m114/try/dawn-win10-x86-deps-rel"
includable_only: true
}
builders {
name: "dawn/try/linux-clang-dbg-x64"
}
builders {
name: "dawn/try/linux-clang-dbg-x86"
}
builders {
name: "dawn/try/linux-clang-rel-x64"
}
builders {
name: "dawn/try/linux-clang-rel-x86"
}
builders {
name: "dawn/try/mac-dbg"
}
builders {
name: "dawn/try/mac-rel"
}
builders {
name: "dawn/try/presubmit"
disable_reuse: true
}
builders {
name: "dawn/try/win-clang-dbg-x64"
}
builders {
name: "dawn/try/win-clang-dbg-x86"
}
builders {
name: "dawn/try/win-clang-rel-x64"
}
builders {
name: "dawn/try/win-clang-rel-x86"
}
builders {
name: "dawn/try/win-msvc-dbg-x64"
}
builders {
name: "dawn/try/win-msvc-rel-x64"
}
retry_config {
single_quota: 1
global_quota: 2
failure_weight: 1
transient_failure_weight: 1
timeout_weight: 2
}
}
}
}

View File

@ -27,10 +27,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-dbg-x64"
@ -48,10 +44,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-dbg-x86"
@ -69,10 +61,6 @@ buckets {
properties_j: "target_cpu:\"x86\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-rel-x64"
@ -90,10 +78,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-rel-x86"
@ -111,10 +95,6 @@ buckets {
properties_j: "target_cpu:\"x86\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "mac-dbg"
@ -136,10 +116,6 @@ buckets {
path: "osx_sdk"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "mac-rel"
@ -161,10 +137,6 @@ buckets {
path: "osx_sdk"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-dbg-x64"
@ -186,10 +158,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-dbg-x86"
@ -211,10 +179,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-rel-x64"
@ -236,10 +200,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-rel-x86"
@ -261,10 +221,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-msvc-dbg-x64"
@ -281,10 +237,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-msvc-rel-x64"
@ -301,10 +253,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
}
}
@ -339,10 +287,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-dbg-x86"
@ -361,10 +305,6 @@ buckets {
properties_j: "target_cpu:\"x86\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-rel-x64"
@ -383,10 +323,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "linux-clang-rel-x86"
@ -405,10 +341,6 @@ buckets {
properties_j: "target_cpu:\"x86\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "mac-dbg"
@ -431,10 +363,6 @@ buckets {
path: "osx_sdk"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "mac-rel"
@ -457,10 +385,6 @@ buckets {
path: "osx_sdk"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "presubmit"
@ -477,10 +401,6 @@ buckets {
properties_j: "runhooks:true"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-dbg-x64"
@ -503,10 +423,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-dbg-x86"
@ -529,10 +445,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-rel-x64"
@ -555,10 +467,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-clang-rel-x86"
@ -581,10 +489,6 @@ buckets {
path: "win_toolchain"
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-msvc-dbg-x64"
@ -602,10 +506,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
builders {
name: "win-msvc-rel-x64"
@ -623,10 +523,6 @@ buckets {
properties_j: "target_cpu:\"x64\""
}
service_account: "dawn-try-builder@chops-service-accounts.iam.gserviceaccount.com"
experiments {
key: "luci.recipes.use_python3"
value: 100
}
}
}
}

View File

@ -7,7 +7,7 @@
name: "dawn"
access: "group:all"
lucicfg {
version: "1.31.3"
version: "1.39.8"
package_dir: ".."
config_dir: "generated"
entry_point: "main.star"

View File

@ -8,13 +8,11 @@
main.star: lucicfg configuration for Dawn's standalone builers.
"""
load("//project.star", "ACTIVE_MILESTONES")
# Use LUCI Scheduler BBv2 names and add Scheduler realms configs.
lucicfg.enable_experiment("crbug.com/1182002")
luci.builder.defaults.experiments.set({
"luci.recipes.use_python3": 100,
})
lucicfg.config(fail_on_warnings = True)
luci.project(
@ -349,16 +347,69 @@ def dawn_standalone_builder(name, clang, debug, cpu, fuzzer = False):
builder = "dawn:try/" + name,
)
def chromium_dawn_tryjob(os):
# These builders run fine unbranched on branch CLs, so add them to the
# branch groups as well.
for milestone in ACTIVE_MILESTONES.keys():
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ-" + milestone,
builder = "dawn:try/" + name,
)
def _add_branch_verifiers(builder_name, os, min_milestone = None, includable_only = False):
for milestone, details in ACTIVE_MILESTONES.items():
if os not in details.platforms:
continue
if min_milestone != None and int(milestone[1:]) < min_milestone:
continue
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ-" + milestone,
builder = "{}:try/{}".format(details.chromium_project, builder_name),
includable_only = includable_only,
)
# We use the DEPS version for branches because ToT builders do not make sense on
# branches and the DEPS versions already exist.
_os_arch_to_branch_builder = {
"linux": "dawn-linux-x64-deps-rel",
"mac": "dawn-mac-x64-deps-rel",
"win": "dawn-win10-x64-deps-rel",
"android-arm": "dawn-android-arm-deps-rel",
"android-arm64": "dawn-android-arm64-deps-rel",
}
# The earliest milestone that the builder is relevant for
_os_arch_to_min_milestone = {
"linux": 112,
"mac": 112,
"win": 112,
"android-arm": 112,
"android-arm64": 115,
}
def chromium_dawn_tryjob(os, arch = None):
"""Adds a tryjob that tests against Chromium
Args:
os: string for the OS, should be one or linux|mac|win
arch: string for the arch, or None
"""
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ",
builder = "chromium:try/" + os + "-dawn-rel",
)
if arch:
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ",
builder = "chromium:try/{os}-dawn-{arch}-rel".format(os = os, arch = arch),
)
_add_branch_verifiers(
_os_arch_to_branch_builder["{os}-{arch}".format(os = os, arch = arch)],
os,
_os_arch_to_min_milestone["{os}-{arch}".format(os = os, arch = arch)],
)
else:
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ",
builder = "chromium:try/{}-dawn-rel".format(os),
)
_add_branch_verifiers(_os_arch_to_branch_builder[os], os)
luci.gitiles_poller(
name = "primary-poller",
@ -411,12 +462,15 @@ dawn_standalone_builder("cron-linux-clang-rel-x64", True, False, "x64", True)
chromium_dawn_tryjob("linux")
chromium_dawn_tryjob("mac")
chromium_dawn_tryjob("win")
chromium_dawn_tryjob("android", "arm")
chromium_dawn_tryjob("android", "arm64")
luci.cq_tryjob_verifier(
cq_group = "Dawn-CQ",
builder = "chromium:try/dawn-try-win10-x86-rel",
includable_only = True,
)
_add_branch_verifiers("dawn-win10-x86-deps-rel", "win", includable_only = True)
# Views
@ -444,33 +498,49 @@ luci.cq(
submit_burst_delay = 480 * time.second,
)
luci.cq_group(
name = "Dawn-CQ",
watch = cq.refset(
"https://dawn.googlesource.com/dawn",
refs = ["refs/heads/.+"],
),
acls = [
acl.entry(
acl.CQ_COMMITTER,
groups = "project-dawn-committers",
def _create_dawn_cq_group(name, refs, refs_exclude = None):
luci.cq_group(
name = name,
watch = cq.refset(
"https://dawn.googlesource.com/dawn",
refs = refs,
refs_exclude = refs_exclude,
),
acl.entry(
acl.CQ_DRY_RUNNER,
groups = "project-dawn-tryjob-access",
acls = [
acl.entry(
acl.CQ_COMMITTER,
groups = "project-dawn-committers",
),
acl.entry(
acl.CQ_DRY_RUNNER,
groups = "project-dawn-tryjob-access",
),
],
verifiers = [
luci.cq_tryjob_verifier(
builder = "dawn:try/presubmit",
disable_reuse = True,
),
],
retry_config = cq.retry_config(
single_quota = 1,
global_quota = 2,
failure_weight = 1,
transient_failure_weight = 1,
timeout_weight = 2,
),
],
verifiers = [
luci.cq_tryjob_verifier(
builder = "dawn:try/presubmit",
disable_reuse = True,
),
],
retry_config = cq.retry_config(
single_quota = 1,
global_quota = 2,
failure_weight = 1,
transient_failure_weight = 1,
timeout_weight = 2,
),
)
def _create_branch_groups():
for milestone, details in ACTIVE_MILESTONES.items():
_create_dawn_cq_group(
"Dawn-CQ-" + milestone,
[details.ref],
)
_create_dawn_cq_group(
"Dawn-CQ",
["refs/heads/.+"],
[details.ref for details in ACTIVE_MILESTONES.values()],
)
_create_branch_groups()

View File

@ -0,0 +1,34 @@
{
"112": {
"name": "m112",
"chromium_project": "chromium-m112",
"ref": "refs/heads/chromium/5615",
"platforms": [
"mac",
"win",
"android"
]
},
"113": {
"name": "m113",
"chromium_project": "chromium-m113",
"ref": "refs/heads/chromium/5672",
"platforms": [
"linux",
"mac",
"win",
"android"
]
},
"114": {
"name": "m114",
"chromium_project": "chromium-m114",
"ref": "refs/heads/chromium/5735",
"platforms": [
"linux",
"mac",
"win",
"android"
]
}
}

View File

@ -0,0 +1,30 @@
#
# Copyright 2023 The Dawn Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
def _milestone_details(*, chromium_project, ref, platforms):
"""Define the details for an active milestone.
Args:
* chromium_project - The name of the LUCI project that is configured for the
milestone.
* ref - The ref in the Dawn git repository that contains the code for the
milestone.
* platforms - A list of platform strings that the milestone is active for.
"""
return struct(
chromium_project = chromium_project,
ref = ref,
platforms = platforms,
)
ACTIVE_MILESTONES = {
m["name"]: _milestone_details(
chromium_project = m["chromium_project"],
ref = m["ref"],
platforms = m["platforms"],
)
for m in json.decode(io.read_file("./milestones.json")).values()
}

View File

@ -0,0 +1,144 @@
#!/usr/bin/env python3
#
# Copyright 2023 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.
"""Script for updating the active milestones for the Dawn project.
This is largely based on the Chromium equivalent in
chromium/src/infra/config/scripts/milestones.py.
To activate a new branch, run the following from the root of the repo (where MMM
is the milestone number and BBBB is the branch number):
```
infra/config/scripts/milestones.py activate --milestone MMM --branch BBBB
infra/config/global/main.star
```
To deactivate a branch, run the following from the root of the repo (where MMM
is the milestone number):
```
infra/config/scripts/milestones.py deactivate --milestone MMM
infra/config/global/main.star
```
"""
import argparse
import json
import os
INFRA_CONFIG_GLOBAL_DIR = os.path.realpath(
os.path.join(os.path.dirname(__file__), '..', 'global'))
def parse_args():
parser = argparse.ArgumentParser(
description='Update the active milestones for the Dawn project')
parser.set_defaults(func=None)
parser.add_argument('--milestones-json',
default=os.path.join(INFRA_CONFIG_GLOBAL_DIR,
'milestones.json'),
help='Path to the milestones.json file to modify')
subparsers = parser.add_subparsers()
activate_parser = subparsers.add_parser(
'activate', help='Add an additional active milestone.')
activate_parser.set_defaults(func=cmd_activate)
activate_parser.add_argument(
'--milestone',
required=True,
type=int,
help='The milestone identifier/release channel number')
activate_parser.add_argument(
'--branch',
required=True,
help='The branch name, which should correspond to a ref in refs/heads')
deactivate_parser = subparsers.add_parser(
'deactivate', help='Remove an active milestone')
deactivate_parser.set_defaults(func=cmd_deactivate)
deactivate_parser.add_argument(
'--milestone',
required=True,
type=int,
help='The milestone identifier/release channel number')
args = parser.parse_args()
if not args.func:
parser.error('No sub-command specified')
return args
def _sort_milestones(milestones):
# We have to manually sort here instead of relying on
# json.dump(..., sort_keys=True) later since we only want to sort the top
# level keys, not all keys.
milestones = {
str(k): milestones[str(k)]
for k in sorted([int(s) for s in milestones])
}
return milestones
def add_milestone(milestones, milestone_num, branch):
if str(milestone_num) in milestones:
raise RuntimeError('Milestone %d already exists' % milestone_num)
milestones[str(milestone_num)] = {
'name': f'm{milestone_num}',
'chromium_project': f'chromium-m{milestone_num}',
'ref': f'refs/heads/{branch}',
'platforms': [
'linux',
'mac',
'win',
'android',
],
}
return _sort_milestones(milestones)
def remove_milestone(milestones, milestone_num):
if str(milestone_num) not in milestones:
raise RuntimeError('Milestone %d does not exist' % milestone_num)
del milestones[str(milestone_num)]
# Not strictly necessary, but returning a value keeps this consistent with
# add_milestone.
return milestones
def cmd_activate(args):
with open(args.milestones_json) as infile:
milestones = json.load(infile)
milestones = add_milestone(milestones, args.milestone, args.branch)
with open(args.milestones_json, 'w') as outfile:
json.dump(milestones, outfile, indent=4)
def cmd_deactivate(args):
with open(args.milestones_json) as infile:
milestones = json.load(infile)
milestones = remove_milestone(milestones, args.milestone)
with open(args.milestones_json, 'w') as outfile:
json.dump(milestones, outfile, indent=4)
def main():
args = parse_args()
args.func(args)
if __name__ == '__main__':
main()

View File

@ -79,7 +79,7 @@ CLONE_SRC_DIR="$(pwd)"
using depot_tools
using go-1.18
using doxygen-1.8.18
using doxygen-1.9.5
status "Creating source directory '${SRC_DIR}' and build directory '${BUILD_DIR}'"
mkdir -p ${SRC_DIR}
@ -129,6 +129,7 @@ if [ "$BUILD_SYSTEM" == "cmake" ]; then
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_MSL_WRITER=1"
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_SPV_WRITER=1"
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_WGSL_WRITER=1"
COMMON_CMAKE_FLAGS+=" -DTINT_RANDOMIZE_HASHES=1"
if [ "$BUILD_TOOLCHAIN" == "clang" ]; then
using clang-10.0.0
@ -137,7 +138,7 @@ if [ "$BUILD_SYSTEM" == "cmake" ]; then
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_AST_FUZZER=1"
COMMON_CMAKE_FLAGS+=" -DTINT_BUILD_REGEX_FUZZER=1"
elif [ "$BUILD_TOOLCHAIN" == "gcc" ]; then
using gcc-9
using gcc-10
fi
if [ "$BUILD_SANITIZER" == "asan" ]; then

View File

@ -44,8 +44,8 @@ exit /b 0
set ORIGINAL_SRC_DIR= %~dp0\..\..\..
set TEMP_DIR=%TEMP%\dawn-temp
set SRC_DIR="%TEMP_DIR%\dawn-src"
set BUILD_DIR="%TEMP_DIR%\dawn-build"
set SRC_DIR=%TEMP_DIR%\dawn-src
set BUILD_DIR=%TEMP_DIR%\dawn-build
cd /d %ORIGINAL_SRC_DIR%
if not exist ".git\" (
@ -105,11 +105,29 @@ copy scripts\standalone.gclient .gclient || goto :error
call gclient sync || goto :error
@echo off
call :status "Adding the Ninja from DEPS to the PATH"
@echo on
set PATH=%SRC_DIR%\third_party\ninja;%PATH%
@echo off
call :status "Configuring build system"
@echo on
mkdir %BUILD_DIR%
cd /d %BUILD_DIR%
set COMMON_CMAKE_FLAGS=-DTINT_BUILD_DOCS=O -DTINT_BUILD_BENCHMARKS=1 -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DTINT_BUILD_BENCHMARKS=1 -DTINT_BUILD_SPV_READER=1 -DTINT_BUILD_WGSL_READER=1 -DTINT_BUILD_GLSL_WRITER=1 -DTINT_BUILD_HLSL_WRITER=1 -DTINT_BUILD_MSL_WRITER=1 -DTINT_BUILD_SPV_WRITER=1 -DTINT_BUILD_WGSL_WRITER=1
set COMMON_CMAKE_FLAGS= ^
-DTINT_BUILD_DOCS=O ^
-DTINT_BUILD_BENCHMARKS=1 ^
-DCMAKE_BUILD_TYPE=%BUILD_TYPE% ^
-DTINT_BUILD_BENCHMARKS=1 ^
-DTINT_BUILD_SPV_READER=1 ^
-DTINT_BUILD_WGSL_READER=1 ^
-DTINT_BUILD_GLSL_WRITER=1 ^
-DTINT_BUILD_HLSL_WRITER=1 ^
-DTINT_BUILD_MSL_WRITER=1 ^
-DTINT_BUILD_SPV_WRITER=1 ^
-DTINT_BUILD_WGSL_WRITER=1 ^
-DTINT_RANDOMIZE_HASHES=1
@echo off
call :status "Building dawn"
@ -138,9 +156,7 @@ cd /d %SRC_DIR% || goto :error
rem Run tests with DXC, FXC and Metal validation
set OLD_PATH=%PATH%
set PATH=C:\Program Files\Metal Developer Tools\macos\bin;%PATH%
where metal.exe
set PATH=%DXC_PATH%;%D3DCOMPILER_PATH%;%OLD_PATH%
call git bash -- ./test/tint/test-all.sh ../dawn-build/tint.exe --verbose || goto :error
call git bash -- ./test/tint/test-all.sh %BUILD_DIR%/tint.exe --verbose || goto :error
set PATH=%OLD_PATH%
@echo off

View File

@ -11,9 +11,9 @@ rm -rf third_party/angle
rm -rf third_party/benchmark
rm -rf third_party/catapult
rm -rf third_party/googletest
rm -rf third_party/google_benchmark
rm -rf third_party/gpuweb-cts
rm -rf third_party/llvm-build
rm -rf third_party/markupsafe
rm -rf third_party/protobuf
rm -rf third_party/swiftshader
rm -rf third_party/vulkan_memory_allocator

View File

@ -32,11 +32,17 @@ if (build_with_chromium) {
dawn_is_winuwp = is_win && target_os == "winuwp"
declare_args() {
dawn_use_angle = true
# TODO(dawn:1545): Re-enable dawn_use_angle on Android. In non-component
# builds, this is adding a dependency on ANGLE's libEGL.so and
# libGLESv2.so, apparently without regard for the use_static_angle=true
# GN variable. Chromium's linker on Android disallows production of more
# than one shared object per target (?).
dawn_use_angle = !is_android
# Enables SwiftShader as the fallback adapter. Requires dawn_swiftshader_dir
# to be set to take effect.
dawn_use_swiftshader = true
# TODO(dawn:1536): Enable SwiftShader for Android.
dawn_use_swiftshader = !is_android
}
declare_args() {
@ -48,6 +54,9 @@ declare_args() {
# standalone to produce static libraries to use in their projects.
dawn_complete_static_libs = false
# Enables the compilation of Dawn's D3D11 backend
dawn_enable_d3d11 = is_win
# Enables the compilation of Dawn's D3D12 backend
dawn_enable_d3d12 = is_win
@ -90,6 +99,10 @@ declare_args() {
# assume to have one present at the system level.
dawn_enable_vulkan_loader =
dawn_enable_vulkan && (is_mac || (is_linux && !is_android))
# Disable SPIR-V validation on Android because it adds a significant amount
# to the binary size, and Tint's output should be well-formed.
dawn_enable_spirv_validation = dawn_enable_vulkan && !is_android
}
# UWP only supports CoreWindow for windowing

View File

@ -22,8 +22,12 @@ import sys
import os
import re
# Assume running the dawn_perf_tests build in Chromium checkout
# Dawn locates at /path/to/Chromium/src/third_party/dawn/
# Chromium build usually locates at /path/to/Chromium/src/out/Release/
# You might want to change the base_path if you want to run dawn_perf_tests build from a Dawn standalone build.
base_path = os.path.abspath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../'))
# Look for a [Rr]elease build.
perftests_paths = glob.glob('out/*elease*')
@ -112,17 +116,19 @@ def get_results(metric, extra_args=[]):
stderr=subprocess.PIPE)
output, err = process.communicate()
m = re.search(r'Running (\d+) tests', output)
output_string = output.decode('utf-8')
m = re.search(r"Running (\d+) tests", output_string)
if m and int(m.group(1)) > 1:
print("Found more than one test result in output:")
print(output)
print(output_string)
sys.exit(3)
pattern = metric + r'.*= ([0-9.]+)'
m = re.findall(pattern, output)
m = re.findall(pattern, output_string)
if not m:
print("Did not find the metric '%s' in the test output:" % metric)
print(output)
print(output_string)
sys.exit(1)
return [float(value) for value in m]

View File

@ -27,10 +27,8 @@ dawn_json_generator("cpp_gen") {
}
source_set("cpp") {
deps = [
":cpp_gen",
"${dawn_root}/include/dawn:cpp_headers",
]
public_deps = [ "${dawn_root}/include/dawn:cpp_headers" ]
deps = [ ":cpp_gen" ]
sources = get_target_outputs(":cpp_gen")
}

View File

@ -23,6 +23,7 @@ add_subdirectory(wire)
# TODO(dawn:269): Remove once the implementation-based swapchains are removed.
add_subdirectory(utils)
add_subdirectory(glfw)
add_subdirectory(tests/benchmarks)
if (DAWN_BUILD_SAMPLES)
#TODO(dawn:269): Add this once implementation-based swapchains are removed.
@ -72,10 +73,7 @@ DawnJSONGenerator(
# because the file doesn't exist on disk.
add_library(dawn_headers STATIC ${DAWN_PLACEHOLDER_FILE})
common_compile_options(dawn_headers)
target_sources(dawn_headers PRIVATE
"${DAWN_INCLUDE_DIR}/dawn/dawn_wsi.h"
${DAWN_HEADERS_GEN_SOURCES}
)
target_sources(dawn_headers PRIVATE ${DAWN_HEADERS_GEN_SOURCES})
target_link_libraries(dawn_headers INTERFACE dawn_public_config)
###############################################################################

View File

@ -18,6 +18,8 @@
#include <cstddef>
#include <new>
namespace dawn {
template <typename T>
T* AllocNoThrow(size_t count) {
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
@ -30,4 +32,6 @@ T* AllocNoThrow(size_t count) {
return new (std::nothrow) T[count];
}
} // namespace dawn
#endif // SRC_DAWN_COMMON_ALLOC_H_

View File

@ -19,6 +19,12 @@
#include "dawn/common/Log.h"
#include "dawn/common/Platform.h"
#if DAWN_COMPILER_IS(MSVC)
extern void __cdecl __debugbreak(void);
#endif
namespace dawn {
#if DAWN_COMPILER_IS(CLANG) || DAWN_COMPILER_IS(GCC)
void BreakPoint() {
#if DAWN_PLATFORM_IS(X86)
@ -27,6 +33,8 @@ void BreakPoint() {
__asm__ __volatile__("bkpt 0");
#elif DAWN_PLATFORM_IS(ARM64)
__asm__ __volatile__("brk 0");
#elif DAWN_PLATFORM_IS(LOONGARCH)
__asm__ __volatile__("break 0");
#elif DAWN_PLATFORM_IS(RISCV)
__asm__ __volatile__("ebreak");
#elif DAWN_PLATFORM_IS(MIPS)
@ -41,7 +49,6 @@ void BreakPoint() {
}
#elif DAWN_COMPILER_IS(MSVC)
extern void __cdecl __debugbreak(void);
void BreakPoint() {
__debugbreak();
}
@ -62,3 +69,5 @@ void HandleAssertionFailure(const char* file,
BreakPoint();
#endif
}
} // namespace dawn

View File

@ -41,11 +41,11 @@
// expect of an assert and in release it tries to give hints to make the compiler generate better
// code.
#if defined(DAWN_ENABLE_ASSERTS)
#define DAWN_ASSERT_CALLSITE_HELPER(file, func, line, condition) \
do { \
if (!(condition)) { \
HandleAssertionFailure(file, func, line, #condition); \
} \
#define DAWN_ASSERT_CALLSITE_HELPER(file, func, line, condition) \
do { \
if (!(condition)) { \
dawn::HandleAssertionFailure(file, func, line, #condition); \
} \
} while (DAWN_ASSERT_LOOP_CONDITION)
#else
#if DAWN_COMPILER_IS(MSVC)
@ -72,9 +72,14 @@
#define UNREACHABLE DAWN_UNREACHABLE
#endif
namespace dawn {
void BreakPoint();
void HandleAssertionFailure(const char* file,
const char* function,
int line,
const char* condition);
} // namespace dawn
#endif // SRC_DAWN_COMMON_ASSERT_H_

View File

@ -58,6 +58,9 @@ config("internal_config") {
]
}
if (dawn_enable_d3d11) {
defines += [ "DAWN_ENABLE_BACKEND_D3D11" ]
}
if (dawn_enable_d3d12) {
defines += [ "DAWN_ENABLE_BACKEND_D3D12" ]
}
@ -80,6 +83,13 @@ config("internal_config") {
defines += [ "DAWN_ENABLE_BACKEND_VULKAN" ]
}
# OS_CHROMEOS cannot be autodetected in runtime and
# cannot be detected with regular compiler macros either.
# Inject it from the build system
if (is_chromeos) {
defines += [ "DAWN_OS_CHROMEOS" ]
}
if (dawn_use_wayland) {
defines += [ "DAWN_USE_WAYLAND" ]
}
@ -236,6 +246,8 @@ if (is_win || is_linux || is_chromeos || is_mac || is_fuchsia || is_android) {
"Log.h",
"Math.cpp",
"Math.h",
"Mutex.cpp",
"Mutex.h",
"NSRef.h",
"NonCopyable.h",
"Numeric.h",
@ -253,7 +265,6 @@ if (is_win || is_linux || is_chromeos || is_mac || is_fuchsia || is_android) {
"SlabAllocator.cpp",
"SlabAllocator.h",
"StackContainer.h",
"SwapChainUtils.h",
"SystemUtils.cpp",
"SystemUtils.h",
"TypeTraits.h",

View File

@ -22,6 +22,8 @@
#include "dawn/common/Math.h"
#include "dawn/common/UnderlyingType.h"
namespace dawn {
// This is ANGLE's BitSetIterator class with a customizable return type.
// Types have been updated to be more specific.
// TODO(crbug.com/dawn/306): it could be optimized, in particular when N <= 64
@ -131,4 +133,6 @@ BitSetIterator<N, uint32_t> IterateBitSet(const std::bitset<N>& bitset) {
return BitSetIterator<N, uint32_t>(bitset);
}
} // namespace dawn
#endif // SRC_DAWN_COMMON_BITSETITERATOR_H_

View File

@ -52,6 +52,8 @@ target_sources(dawn_common PRIVATE
"Log.h"
"Math.cpp"
"Math.h"
"Mutex.cpp"
"Mutex.h"
"NSRef.h"
"NonCopyable.h"
"Numeric.h"
@ -69,7 +71,6 @@ target_sources(dawn_common PRIVATE
"SlabAllocator.cpp"
"SlabAllocator.h"
"StackContainer.h"
"SwapChainUtils.h"
"SystemUtils.cpp"
"SystemUtils.h"
"TypeTraits.h"

View File

@ -21,6 +21,8 @@
#include "dawn/common/NonCopyable.h"
namespace dawn {
template <typename T>
class ConcurrentCache : public NonMovable {
public:
@ -51,4 +53,6 @@ class ConcurrentCache : public NonMovable {
std::unordered_set<T*, typename T::HashFunc, typename T::EqualityFunc> mCache;
};
} // namespace dawn
#endif // SRC_DAWN_COMMON_CONCURRENTCACHE_H_

Some files were not shown because too many files have changed in this diff Show More