diff options
203 files changed, 3514 insertions, 1401 deletions
diff --git a/.gitignore b/.gitignore index af83ec392f..3d9ffa76a1 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ /third_party/fuchsia-sdk /third_party/gles1_conform /third_party/glmark2/src +/third_party/glslang/src /third_party/googletest /third_party/ijar /third_party/jdk/current @@ -89,10 +90,18 @@ /third_party/rapidjson/src /third_party/requests/src /third_party/six +/third_party/spirv-cross/src +/third_party/spirv-headers/src +/third_party/spirv-tools/src /third_party/SwiftShader /third_party/turbine/*.jar /third_party/VK-GL-CTS/src /third_party/vulkan-deps +/third_party/vulkan-headers/src +/third_party/vulkan-loader/src +/third_party/vulkan-tools/src +/third_party/vulkan-utility-libraries/src +/third_party/vulkan-validation-layers/src /third_party/vulkan_memory_allocator /third_party/wayland /third_party/zlib diff --git a/.gitmodules b/.gitmodules index d8ca36b452..f5f80fd062 100644 --- a/.gitmodules +++ b/.gitmodules @@ -92,7 +92,7 @@ [submodule "third_party/libdrm"] path = third_party/libdrm url = https://chromium.googlesource.com/chromiumos/third_party/libdrm - gclient-condition = checkout_angle_mesa + gclient-condition = checkout_angle_mesa or not build_with_chromium [submodule "third_party/libjpeg_turbo"] path = third_party/libjpeg_turbo url = https://chromium.googlesource.com/chromium/deps/libjpeg_turbo @@ -108,7 +108,7 @@ [submodule "third_party/jinja2"] path = third_party/jinja2 url = https://chromium.googlesource.com/chromium/src/third_party/jinja2 - gclient-condition = checkout_android and not build_with_chromium + gclient-condition = not build_with_chromium [submodule "third_party/jsoncpp"] path = third_party/jsoncpp url = https://chromium.googlesource.com/chromium/src/third_party/jsoncpp @@ -128,7 +128,7 @@ [submodule "third_party/markupsafe"] path = third_party/markupsafe url = https://chromium.googlesource.com/chromium/src/third_party/markupsafe - gclient-condition = checkout_android and not build_with_chromium + gclient-condition = not build_with_chromium [submodule "third_party/mesa/src"] path = third_party/mesa/src url = https://chromium.googlesource.com/external/github.com/Mesa3D/mesa @@ -160,7 +160,7 @@ [submodule "third_party/perfetto"] path = third_party/perfetto url = https://android.googlesource.com/platform/external/perfetto - gclient-condition = not build_with_chromium and checkout_angle_restricted_traces + gclient-condition = not build_with_chromium and checkout_angle_perfetto [submodule "third_party/protobuf"] path = third_party/protobuf url = https://chromium.googlesource.com/chromium/src/third_party/protobuf @@ -191,6 +191,42 @@ path = third_party/vulkan-deps url = https://chromium.googlesource.com/vulkan-deps gclient-condition = not build_with_chromium +[submodule "third_party/glslang/src"] + path = third_party/glslang/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/glslang + gclient-condition = not build_with_chromium +[submodule "third_party/spirv-cross/src"] + path = third_party/spirv-cross/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross + gclient-condition = not build_with_chromium +[submodule "third_party/spirv-headers/src"] + path = third_party/spirv-headers/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers + gclient-condition = not build_with_chromium +[submodule "third_party/spirv-tools/src"] + path = third_party/spirv-tools/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools + gclient-condition = not build_with_chromium +[submodule "third_party/vulkan-headers/src"] + path = third_party/vulkan-headers/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers + gclient-condition = not build_with_chromium +[submodule "third_party/vulkan-loader/src"] + path = third_party/vulkan-loader/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Loader + gclient-condition = not build_with_chromium +[submodule "third_party/vulkan-tools/src"] + path = third_party/vulkan-tools/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools + gclient-condition = not build_with_chromium +[submodule "third_party/vulkan-utility-libraries/src"] + path = third_party/vulkan-utility-libraries/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries + gclient-condition = not build_with_chromium +[submodule "third_party/vulkan-validation-layers/src"] + path = third_party/vulkan-validation-layers/src + url = https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-ValidationLayers + gclient-condition = not build_with_chromium [submodule "third_party/vulkan_memory_allocator"] path = third_party/vulkan_memory_allocator url = https://chromium.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator @@ -53,6 +53,8 @@ default_args = { # Use base level API level 29 support for AHardwareBuffer ANGLE tests. android32_ndk_api_level = 29 android64_ndk_api_level = 29 + + vma_vulkan_headers_dir = "//third_party/vulkan-headers/src" } no_check_targets = [ "third_party/dawn/*" ] @@ -1244,16 +1244,10 @@ config("angle_abseil_config") { group("angle_abseil") { if (angle_enable_abseil) { # When build_with_chromium=true we need to include "//third_party/abseil-cpp:absl" while - # we can be more specific when building standalone ANGLE. - if (build_with_chromium) { + # we can be more specific when building standalone non-component ANGLE. + # Also build the combined target when building Dawn to avoid multiply defined globals. + if (build_with_chromium || angle_enable_wgpu || is_component_build) { public_deps = [ "$angle_abseil_cpp_dir:absl" ] - } else if (angle_enable_wgpu) { - # Use Dawn's abseil build files when Dawn will also be built. Multiple build targets - # with the same files causes link issues in component builds. - public_deps = [ - "$angle_dawn_dir/third_party/gn/abseil-cpp:flat_hash_map", - "$angle_dawn_dir/third_party/gn/abseil-cpp:flat_hash_set", - ] } else { public_deps = [ "$angle_abseil_cpp_dir/absl/container:flat_hash_map", @@ -43,13 +43,13 @@ vars = { 'checkout_angle_mesa': False, # Version of Chromium our Chromium-based DEPS are mirrored from. - 'chromium_revision': '4fea14b56dd7d46a28e566671c06cdd0a92fc4d1', + 'chromium_revision': '1daa08898eedcd1371baaa095c129cf56bbff3da', # We never want to checkout chromium, # but need a dummy DEPS entry for the autoroller 'dummy_checkout_chromium': False, # Current revision of VK-GL-CTS (a.k.a dEQP). - 'vk_gl_cts_revision': '9d7b4c3d553331e316321942e2eb8413e4081c79', + 'vk_gl_cts_revision': 'fd5cc7b1e07578e8e807696034ab894b134f4280', # Current revision of googletest. # Note: this dep cannot be auto-rolled b/c of nesting. @@ -88,16 +88,16 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '47d3198a953f28d06b46bb6f9293b4e0b384d155', + 'catapult_revision': 'ec40c25bd83f043ebc76fb368414016b0515675b', # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:20.20240507.3.1', + 'fuchsia_version': 'version:20.20240522.3.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling luci-go # and whatever else without interference from each other. - 'luci_go': 'git_revision:91ca2f5af39c4feb1c748c353f4d616e1c2332e7', + 'luci_go': 'git_revision:4967d21f2b92546ac3747086cdcbb046b6db52fb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version @@ -130,10 +130,10 @@ vars = { # reclient CIPD package 'reclient_package': 'infra/rbe/client/', # reclient CIPD package version - 'reclient_version': 're_client_version:0.141.1.29a9d3c-gomaip', + 'reclient_version': 're_client_version:0.143.0.518e369-gomaip', # siso CIPD package version. - 'siso_version': 'git_revision:4524544994f4eac131378143f498ee4d0b7d1f36', + 'siso_version': 'git_revision:df7a992166415f66f6958744f149f724df138879', # 'magic' text to tell depot_tools that git submodules should be accepted but # but parity with DEPS file is expected. @@ -141,7 +141,7 @@ vars = { # Make Dawn skip its standalone dependencies 'dawn_standalone': False, - 'dawn_revision': '5406e9dfbe0ba766e5a7571e1ad7c2dc48ad57e7', + 'dawn_revision': 'd32858a3045a89e8c5ff919107ee76c8b103afdf', # All of the restricted traces (large). 'checkout_angle_restricted_traces': 'checkout_angle_internal', @@ -415,12 +415,12 @@ vars = { deps = { 'build': { - 'url': Var('chromium_git') + '/chromium/src/build.git@7796c50af5b192c01d7c92f930de2093a8507097', + 'url': Var('chromium_git') + '/chromium/src/build.git@59a9be4050c182588808e01f79d6d743e9351034', 'condition': 'not build_with_chromium', }, 'buildtools': { - 'url': Var('chromium_git') + '/chromium/src/buildtools.git@9703d9137fff0cb447779de1bfebbe18ea312f89', + 'url': Var('chromium_git') + '/chromium/src/buildtools.git@efa920ce144e4dc1c1841e73179cd7e23b9f0d5e', 'condition': 'not build_with_chromium', }, @@ -433,7 +433,7 @@ deps = { 'packages': [ { 'package': 'gn/gn/linux-${{arch}}', - 'version': 'git_revision:f284b6b47039a2d7edfcbfc51f52664f82b5a789', + 'version': 'git_revision:df98b86690c83b81aedc909ded18857296406159', } ], 'dep_type': 'cipd', @@ -444,7 +444,7 @@ deps = { 'packages': [ { 'package': 'gn/gn/mac-${{arch}}', - 'version': 'git_revision:f284b6b47039a2d7edfcbfc51f52664f82b5a789', + 'version': 'git_revision:df98b86690c83b81aedc909ded18857296406159', } ], 'dep_type': 'cipd', @@ -466,7 +466,7 @@ deps = { 'packages': [ { 'package': 'gn/gn/windows-amd64', - 'version': 'git_revision:f284b6b47039a2d7edfcbfc51f52664f82b5a789', + 'version': 'git_revision:df98b86690c83b81aedc909ded18857296406159', } ], 'dep_type': 'cipd', @@ -474,12 +474,12 @@ deps = { }, 'testing': { - 'url': '{chromium_git}/chromium/src/testing@a2a6e48c98e5e5869e822b542e935514d843c436', + 'url': '{chromium_git}/chromium/src/testing@940cfd4db1dfb7712cb94d68f19e476f6ed6e3ad', 'condition': 'not build_with_chromium', }, 'third_party/abseil-cpp': { - 'url': Var('chromium_git') + '/chromium/src/third_party/abseil-cpp@31bdf8fec41f04dfe86976734cbad22ded4ca1f7', + 'url': Var('chromium_git') + '/chromium/src/third_party/abseil-cpp@b027bd3c0b3ce035c8da06a78e7ab8db2d5c4444', 'condition': 'not build_with_chromium', }, @@ -525,7 +525,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'Y5wuGPB-HfFtEVQC_0XI6n88Covm4HFDxnG0uTdV2LcC', + 'version': '802fuDf2tCI5HIcMNx1jWJbsTrLt2DS5z8BuFE_Sx7cC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -536,7 +536,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'tz8dYQ_yBEZJRVhtzyyCjOlbOfujkHRWcYZy7419o_cC', + 'version': 'EBQZXvDztclHzavY9ulEJA3r4mn0PmbIMeKYKnzhEoEC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -544,7 +544,7 @@ deps = { }, 'third_party/android_deps': { - 'url': Var('chromium_git') + '/chromium/src/third_party/android_deps@36a6c64282adbe58f343d9c0cbdf45d0e6402db3', + 'url': Var('chromium_git') + '/chromium/src/third_party/android_deps@2888a739e9b8b8514807a5a0d8b26f91a7e4e91d', 'condition': 'checkout_android and not build_with_chromium', }, @@ -656,7 +656,7 @@ deps = { }, 'third_party/depot_tools': { - 'url': Var('chromium_git') + '/chromium/tools/depot_tools.git@df437783c243fef294e6af2e44de383e751a3764', + 'url': Var('chromium_git') + '/chromium/tools/depot_tools.git@09c232e7c0d5670695d1f8f70d05ed1a215e438c', 'condition': 'not build_with_chromium', }, @@ -673,7 +673,7 @@ deps = { }, 'third_party/flatbuffers/src': { - 'url': Var('chromium_git') + '/external/github.com/google/flatbuffers.git@bcb9ef187628fe07514e57756d05e6a6296f7dc5', + 'url': Var('chromium_git') + '/external/github.com/google/flatbuffers.git@150644d7f4d030a0629c564fd90dc3becab77636', 'condition': 'checkout_android and not build_with_chromium', }, @@ -713,7 +713,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlin_stdlib', - 'version': '05hzFgOi0AqRK3RxbSvGj2TWTFUNeLcwkJwVzwgLttUC', + 'version': '_4e0lDaCjMgaNeq2v2olJs_15Ax3PxGfCU9fMt0FTKcC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -775,17 +775,17 @@ deps = { }, 'third_party/libc++/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxx.git@e3b94d0e5b86883fd77696bf10dc33ba250ba99b', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxx.git@852bc6746f45add53fec19f3a29280e69e358d44', 'condition': 'not build_with_chromium', }, 'third_party/libc++abi/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxxabi.git@d17298ab09b44bbc95e5e59c0f285145d0e5f8a7', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libcxxabi.git@ba370858669b1e905db5ded82c8887095b61dc14', 'condition': 'not build_with_chromium', }, 'third_party/libunwind/src': { - 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libunwind.git@419b03c0b8f20d6da9ddcb0d661a94a97cdd7dad', + 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project/libunwind.git@e0a4f3561e7f7ce10573917b60c7027e3b599e65', 'condition': 'not build_with_chromium', }, @@ -872,7 +872,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'ntlyos9oLHW_q1AeZovqFuTYzog9dKd2lITTowptHuYC', + 'version': '2VsAp2dMXnrxyG6_BD0El4gDAxTXPqrw8xCV0MNmxcUC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -919,7 +919,7 @@ deps = { }, 'third_party/SwiftShader': { - 'url': Var('swiftshader_git') + '/SwiftShader@da334852e70510d259bfa8cbaa7c5412966b2f41', + 'url': Var('swiftshader_git') + '/SwiftShader@90519141a709a92db90640b52176aaf82942e937', 'condition': 'not build_with_chromium', }, @@ -927,7 +927,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/turbine', - 'version': 'fYpnoJAvh8-OaNB9k81XWGrwiODb_uTipTBEUeIFM98C', + 'version': 'JA8o86DtHkYnsW4v8F9pdcvi7uqN1WB-L1XFLggZdtAC', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -939,7 +939,52 @@ deps = { }, 'third_party/vulkan-deps': { - 'url': Var('chromium_git') + '/vulkan-deps@643408ea2a0685352d831a97601997c9ea246f6f', + 'url': Var('chromium_git') + '/vulkan-deps@feb3ce48e50956465d171e37c548bb8e44a30efa', + 'condition': 'not build_with_chromium', + }, + + 'third_party/glslang/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/glslang@7c3c50ea94354d06dc8c280de8b8a5d5aacbbb19', + 'condition': 'not build_with_chromium', + }, + + 'third_party/spirv-cross/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', + 'condition': 'not build_with_chromium', + }, + + 'third_party/spirv-headers/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@49a1fceb9b1d087f3c25ad5ec077bb0e46231297', + 'condition': 'not build_with_chromium', + }, + + 'third_party/spirv-tools/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@77c40bece1b8b441eee432fc9d74efbf985f777f', + 'condition': 'not build_with_chromium', + }, + + 'third_party/vulkan-headers/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@5677bafb820e476441e9e1f745371b72133407d3', + 'condition': 'not build_with_chromium', + }, + + 'third_party/vulkan-loader/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@d3d530c90dd6549bcfc7cfaedd3ff85fe8ff04a2', + 'condition': 'not build_with_chromium', + }, + + 'third_party/vulkan-tools/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@d67a9d3a394e11c1c4c0f480124f5b7925cb1b4d', + 'condition': 'not build_with_chromium', + }, + + 'third_party/vulkan-utility-libraries/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@f6c54531066c6d28ef403b50ff9cff3ea195d28a', + 'condition': 'not build_with_chromium', + }, + + 'third_party/vulkan-validation-layers/src': { + 'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@b25dea41d4a441268745ed9a83f82757170ec459', 'condition': 'not build_with_chromium', }, @@ -954,17 +999,17 @@ deps = { }, 'third_party/zlib': { - 'url': Var('chromium_git') + '/chromium/src/third_party/zlib@7d77fb7fd66d8a5640618ad32c71fdeb7d3e02df', + 'url': Var('chromium_git') + '/chromium/src/third_party/zlib@209717dd69cd62f24cbacc4758261ae2dd78cfac', 'condition': 'not build_with_chromium', }, 'tools/android': { - 'url': Var('chromium_git') + '/chromium/src/tools/android@cc51a5ea8611565ff48db1a11c08e90d03484bd2', + 'url': Var('chromium_git') + '/chromium/src/tools/android@34192533e15dd37bd3c91910247fb925d1e15327', 'condition': 'checkout_android and not build_with_chromium', }, 'tools/clang': { - 'url': Var('chromium_git') + '/chromium/src/tools/clang.git@964cf5c799c2284d52a88b1a516481852e7a216f', + 'url': Var('chromium_git') + '/chromium/src/tools/clang.git@9772a0a3490ed8f5977babbb01182944b44d3ea8', 'condition': 'not build_with_chromium', }, @@ -995,7 +1040,7 @@ deps = { }, 'tools/mb': { - 'url': Var('chromium_git') + '/chromium/src/tools/mb@54a120d570f317c69bb155481629e2121df75546', + 'url': Var('chromium_git') + '/chromium/src/tools/mb@973c25352084d231639ecd6f110e8343e203defb', 'condition': 'not build_with_chromium', }, @@ -1010,7 +1055,7 @@ deps = { }, 'tools/perf': { - 'url': Var('chromium_git') + '/chromium/src/tools/perf@7ef4ff5ba36be22f641d0f08f34402f85db18492', + 'url': Var('chromium_git') + '/chromium/src/tools/perf@ce2f1c1daa5716c697105213772e13be838ee441', 'condition': 'not build_with_chromium', }, @@ -1028,7 +1073,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'rnVa2tBzy_bWBzhMbfGN9LWVREg2oX7FIWTizcil9nAC', + 'version': 'WMIZj5iCtXaIDiOhz7iiswLMOl8EWWP5gfRyHAEZUSAC', }, ], 'dep_type': 'cipd', @@ -1039,7 +1084,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'qWfDi1N2HXBm5wLJgsy6fImu51jqJ6JafFDWjWJPuMQC', + 'version': 'zHUBIGOiczuqjD1DhUqsPCLIcVp7c-7bnuOzAncAsy0C', }, ], 'dep_type': 'cipd', @@ -1050,7 +1095,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'Y1vx6zBEl8AgYA0BE99RK71LoJPAJMdFcFZUiiH4ItIC', + 'version': '88_YxpnUWyvy_qTnp6FH2cvFsJ3eKeNLLph6CbyXHmoC', }, ], 'dep_type': 'cipd', @@ -1061,7 +1106,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': '1QeDGa3HwvjmY-wV4NK81PTGZGJ_uSZ0FSC0dHAosIsC', + 'version': 'TtqdFmghiNp8fsnpcuBhyC8e9PjVxKAXDBQhNoTReaUC', }, ], 'dep_type': 'cipd', @@ -4904,7 +4949,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_bouncycastle_bcprov_jdk18on', - 'version': 'version:2@1.76.cr1', + 'version': 'version:2@1.77.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5168,7 +5213,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm', - 'version': 'version:2@9.6.cr1', + 'version': 'version:2@9.7.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5179,7 +5224,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_analysis', - 'version': 'version:2@9.6.cr1', + 'version': 'version:2@9.7.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5190,7 +5235,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_commons', - 'version': 'version:2@9.6.cr1', + 'version': 'version:2@9.7.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5201,7 +5246,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_tree', - 'version': 'version:2@9.6.cr1', + 'version': 'version:2@9.7.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5212,7 +5257,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_ow2_asm_asm_util', - 'version': 'version:2@9.6.cr1', + 'version': 'version:2@9.7.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5234,7 +5279,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_annotations', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5245,7 +5290,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_junit', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5256,7 +5301,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5267,7 +5312,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_nativeruntime_dist_compat', - 'version': 'version:2@1.0.2.cr1', + 'version': 'version:2@1.0.9.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5278,7 +5323,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_pluginapi', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5289,7 +5334,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5300,7 +5345,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_resources', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5311,7 +5356,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_robolectric', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5322,7 +5367,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_sandbox', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5333,7 +5378,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadowapi', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5344,7 +5389,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadows_framework', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5355,7 +5400,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_shadows_versioning', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5366,7 +5411,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5377,7 +5422,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_robolectric_utils_reflector', - 'version': 'version:2@4.11.1.cr1', + 'version': 'version:2@4.12.1.cr1', }, ], 'condition': 'checkout_android and not build_with_chromium', @@ -5654,7 +5699,6 @@ hooks = [ recursedeps = [ 'third_party/googletest', 'third_party/jsoncpp', - 'third_party/vulkan-deps', 'third_party/dawn', ] @@ -54,6 +54,7 @@ per-file third_party/EGL-Registry/src=* per-file third_party/flatbuffers/src=* per-file third_party/gles1_conform=* per-file third_party/glmark2/src=* +per-file third_party/glslang/src=* per-file third_party/googletest=* per-file third_party/ijar=* per-file third_party/libdrm=* @@ -77,9 +78,17 @@ per-file third_party/Python-Markdown=* per-file third_party/rapidjson/src=* per-file third_party/requests/src=* per-file third_party/six=* +per-file third_party/spirv-cross/src=* +per-file third_party/spirv-headers/src=* +per-file third_party/spirv-tools/src=* per-file third_party/SwiftShader=* per-file third_party/VK-GL-CTS/src=* per-file third_party/vulkan-deps=* +per-file third_party/vulkan-headers/src=* +per-file third_party/vulkan-loader/src=* +per-file third_party/vulkan-tools/src=* +per-file third_party/vulkan-utility-libraries/src=* +per-file third_party/vulkan-validation-layers/src=* per-file third_party/vulkan_memory_allocator=* per-file third_party/wayland=* per-file third_party/zlib=* diff --git a/build b/build -Subproject 7796c50af5b192c01d7c92f930de2093a850709 +Subproject 59a9be4050c182588808e01f79d6d743e935103 diff --git a/build_overrides/angle.gni b/build_overrides/angle.gni index 48f3993b5d..dcd98eb8f9 100644 --- a/build_overrides/angle.gni +++ b/build_overrides/angle.gni @@ -10,13 +10,13 @@ angle_has_build = true # Overrides for ANGLE's dependencies angle_abseil_cpp_dir = "//third_party/abseil-cpp" -angle_glslang_dir = "//third_party/vulkan-deps/glslang/src" +angle_glslang_dir = "//third_party/glslang/src" angle_googletest_dir = "//third_party/googletest/src" angle_jsoncpp_dir = "//third_party/jsoncpp" angle_libjpeg_turbo_dir = "//third_party/libjpeg_turbo" angle_libpng_dir = "//third_party/libpng" -angle_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src" -angle_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src" +angle_spirv_headers_dir = "//third_party/spirv-headers/src" +angle_spirv_tools_dir = "//third_party/spirv-tools/src" angle_vulkan_memory_allocator_dir = "//third_party/vulkan_memory_allocator" angle_clspv_dir = "//third_party/clspv" angle_llvm_dir = "//third_party/llvm/src" diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni index c1b38f7be7..85bb1ae014 100644 --- a/build_overrides/dawn.gni +++ b/build_overrides/dawn.gni @@ -1,4 +1,5 @@ build_with_chromium = false +build_with_angle = true dawn_build_dxc = false dawn_angle_dir = "//" @@ -6,11 +7,12 @@ dawn_glfw_dir = "//third_party/dawn/third_party/glfw" dawn_googletest_dir = "//third_party/googletest/src" dawn_jinja2_dir = "//third_party/jinja2" dawn_jsoncpp_dir = "//third_party/jsoncpp" -dawn_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src" +dawn_spirv_tools_dir = "//third_party/spirv-tools/src" dawn_swiftshader_dir = "//third_party/SwiftShader" -dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src" -dawn_vulkan_validation_layers_dir = - "//third_party/vulkan-deps/vulkan-validation-layers/src" +dawn_vulkan_headers_dir = "//third_party/vulkan-headers/src" +dawn_vulkan_loader_dir = "//third_party/vulkan-loader/src" +dawn_vulkan_utility_libraries_dir = "//third_party/vulkan-utility-libraries/src" +dawn_vulkan_validation_layers_dir = "//third_party/vulkan-validation-layers/src" dawn_dxc_dir = "//third_party/dawn/third_party/dxc" dawn_dxheaders_dir = "//third_party/dawn/third_party/dxheaders" dawn_opengl_registry_dir = "//third_party/OpenGL-Registry/src" diff --git a/build_overrides/glslang.gni b/build_overrides/glslang.gni index c32adf60b3..534d55d911 100644 --- a/build_overrides/glslang.gni +++ b/build_overrides/glslang.gni @@ -3,4 +3,4 @@ # found in the LICENSE file. # Paths to glslang dependencies in ANGLE -glslang_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src" +glslang_spirv_tools_dir = "//third_party/spirv-tools/src" diff --git a/build_overrides/spirv_tools.gni b/build_overrides/spirv_tools.gni index 3c9b43ad97..adfa08b6d8 100644 --- a/build_overrides/spirv_tools.gni +++ b/build_overrides/spirv_tools.gni @@ -7,4 +7,4 @@ spirv_tools_standalone = false # Paths to SPIRV-Tools dependencies in ANGLE spirv_tools_googletest_dir = "//third_party/googletest/src" -spirv_tools_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src" +spirv_tools_spirv_headers_dir = "//third_party/spirv-headers/src" diff --git a/build_overrides/tint.gni b/build_overrides/tint.gni index ee43d60929..4e41a6aa72 100644 --- a/build_overrides/tint.gni +++ b/build_overrides/tint.gni @@ -4,9 +4,9 @@ tint_has_build = false tint_build_unittests = false tint_root_dir = "//third_party/dawn" -tint_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src" +tint_spirv_tools_dir = "//third_party/spirv-tools/src" tint_googletest_dir = "//third_party/googletest/src" -tint_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src" +tint_spirv_headers_dir = "//third_party/spirv-headers/src" tint_build_spv_reader = false tint_build_spv_writer = true diff --git a/build_overrides/vulkan_validation_layers.gni b/build_overrides/vulkan_validation_layers.gni index c57af506d3..d47b6c7a7f 100644 --- a/build_overrides/vulkan_validation_layers.gni +++ b/build_overrides/vulkan_validation_layers.gni @@ -4,8 +4,7 @@ import("//build_overrides/vulkan_common.gni") -vulkan_utility_libraries_dir = - "//third_party/vulkan-deps/vulkan-utility-libraries/src" -vvl_spirv_tools_dir = "//third_party/vulkan-deps/spirv-tools/src" -vvl_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src" -vvl_glslang_dir = "//third_party/vulkan-deps/glslang/src" +vulkan_utility_libraries_dir = "//third_party/vulkan-utility-libraries/src" +vvl_spirv_tools_dir = "//third_party/spirv-tools/src" +vvl_spirv_headers_dir = "//third_party/spirv-headers/src" +vvl_glslang_dir = "//third_party/glslang/src" diff --git a/buildtools b/buildtools -Subproject 9703d9137fff0cb447779de1bfebbe18ea312f8 +Subproject efa920ce144e4dc1c1841e73179cd7e23b9f0d5 diff --git a/extensions/EGL_ANGLE_device_d3d11.txt b/extensions/EGL_ANGLE_device_d3d11.txt new file mode 100644 index 0000000000..a90b95c80f --- /dev/null +++ b/extensions/EGL_ANGLE_device_d3d11.txt @@ -0,0 +1,89 @@ +Name + + ANGLE_device_d3d11 + +Name Strings + + EGL_ANGLE_device_d3d11 + +Contributors + + Geoff Lang (geofflang 'at' google.com) + Contributors of EGL_ANGLE_device_d3d + +Contact + + Geoff Lang (geofflang 'at' google.com) + +Status + + Draft + +Version + + Version 1, May 21, 2024 + +Number + + EGL Extension #XXX + +Extension Type + + EGL device extension + +Dependencies + + This extension is written against the language of EGL 1.5 as + modified by EGL_EXT_device_query. + + EGL_EXT_device_query is required. + +Overview + + ANGLE has the ability to run GPU commands on a native D3D11 device. + This extension defines a mapping from an EGL device to a D3D11 + device, after it's queried from an EGL display. + +IP Status + + No known claims. + +New Types + + None. + +New Procedures and Functions + + None. + +New Tokens + + Accepted as a queried <attribute> in eglQueryDeviceAttribEXT: + + EGL_D3D11_DEVICE_ANGLE 0x33A1 + +Add a new section 2.1.3 (D3D11 Devices) after 2.1.2 (Devices) + + Somewhat analogous to an EGL device, a D3D11 device establishes a + namespace for D3D operations. In the D3D APIs, such devices are + represented by pointers. For more details, see the D3D11 + documentation. + +Changes to section 3.2 (Devices) + + Replace the paragraph immediately following the prototype for + eglQueryDeviceAttribEXT: + + <attribute> may EGL_D3D11_DEVICE_ANGLE. On success, EGL_TRUE is + returned, and a valid D3D11 device pointer corresponding to the EGL + device is returned in <value>. This handle is compatible with D3D11 + API functions. + +Issues + + None + +Revision History + + Version 1, May 21, 2024 (Geoff Lang) + - Initial Draft, based off of EGL_ANGLE_device_d3d diff --git a/extensions/EGL_ANGLE_device_d3d9.txt b/extensions/EGL_ANGLE_device_d3d9.txt new file mode 100644 index 0000000000..07137260c6 --- /dev/null +++ b/extensions/EGL_ANGLE_device_d3d9.txt @@ -0,0 +1,89 @@ +Name + + ANGLE_device_d3d9 + +Name Strings + + EGL_ANGLE_device_d3d9 + +Contributors + + Geoff Lang (geofflang 'at' google.com) + Contributors of EGL_ANGLE_device_d3d + +Contact + + Geoff Lang (geofflang 'at' google.com) + +Status + + Draft + +Version + + Version 1, May 21, 2024 + +Number + + EGL Extension #XXX + +Extension Type + + EGL device extension + +Dependencies + + This extension is written against the language of EGL 1.5 as + modified by EGL_EXT_device_query. + + EGL_EXT_device_query is required. + +Overview + + ANGLE has the ability to run GPU commands on a native D3D9 device. + This extension defines a mapping from an EGL device to a D3D9 + device, after it's queried from an EGL display. + +IP Status + + No known claims. + +New Types + + None. + +New Procedures and Functions + + None. + +New Tokens + + Accepted as a queried <attribute> in eglQueryDeviceAttribEXT: + + EGL_D3D9_DEVICE_ANGLE 0x33A0 + +Add a new section 2.1.3 (D3D9 Devices) after 2.1.2 (Devices) + + Somewhat analogous to an EGL device, a D3D9 device establishes a + namespace for D3D operations. In the D3D APIs, such devices are + represented by pointers. For more details, see the D3D9 + documentation. + +Changes to section 3.2 (Devices) + + Replace the paragraph immediately following the prototype for + eglQueryDeviceAttribEXT: + + <attribute> may EGL_D3D9_DEVICE_ANGLE. On success, EGL_TRUE is + returned, and a valid D3D9 device pointer corresponding to the EGL + device is returned in <value>. This handle is compatible with D3D9 + API functions. + +Issues + + None + +Revision History + + Version 1, May 21, 2024 (Geoff Lang) + - Initial Draft, based off of EGL_ANGLE_device_d3d diff --git a/gni/angle.gni b/gni/angle.gni index 2feede6743..a9ddfa3a02 100644 --- a/gni/angle.gni +++ b/gni/angle.gni @@ -293,14 +293,11 @@ declare_args() { # Directory where to find wayland source files angle_wayland_dir = "$angle_root/third_party/wayland" - angle_vulkan_headers_dir = - "$angle_root/third_party/vulkan-deps/vulkan-headers/src" - angle_vulkan_loader_dir = - "$angle_root/third_party/vulkan-deps/vulkan-loader/src" - angle_vulkan_tools_dir = - "$angle_root/third_party/vulkan-deps/vulkan-tools/src" + angle_vulkan_headers_dir = "$angle_root/third_party/vulkan-headers/src" + angle_vulkan_loader_dir = "$angle_root/third_party/vulkan-loader/src" + angle_vulkan_tools_dir = "$angle_root/third_party/vulkan-tools/src" angle_vulkan_validation_layers_dir = - "$angle_root/third_party/vulkan-deps/vulkan-validation-layers/src" + "$angle_root/third_party/vulkan-validation-layers/src" angle_build_vulkan_system_info = angle_has_build && !angle_is_winuwp diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg index f1983aa985..a0cdc90829 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci-milo.cfg @@ -71,11 +71,6 @@ consoles { short_name: "dbg" } builders { - name: "buildbucket/luci.angle.ci/mac-exp-test" - category: "test|mac|x64" - short_name: "exp" - } - builders { name: "buildbucket/luci.angle.ci/mac-test" category: "test|mac|x64" short_name: "rel" @@ -186,6 +181,9 @@ consoles { name: "buildbucket/luci.angle.ci/linux-exp-tsan-test" } builders { + name: "buildbucket/luci.angle.ci/mac-exp-test" + } + builders { name: "buildbucket/luci.angle.ci/win-exp-test" } builder_view_only: true diff --git a/infra/config/main.star b/infra/config/main.star index 1533f831f6..cfbaeb8572 100755 --- a/infra/config/main.star +++ b/infra/config/main.star @@ -323,7 +323,6 @@ def angle_builder(name, cpu): "android-arm64-exp-test", "android-arm64-exp-s22-test", "linux-exp-test", - "mac-exp-test", ] if (not is_exp) or (name in active_experimental_builders): diff --git a/infra/specs/angle.json b/infra/specs/angle.json index d599aee141..ac35e33f58 100644 --- a/infra/specs/angle.json +++ b/infra/specs/angle.json @@ -5641,7 +5641,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -5665,7 +5665,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -5690,7 +5690,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -5715,7 +5715,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -5740,7 +5740,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -5766,7 +5766,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -5792,7 +5792,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -5814,209 +5814,7 @@ "display_attached": "1", "gpu": "1002:67ef", "hidpi": "1", - "os": "Mac-13.5", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "angle_unittests", - "test_id_prefix": "ninja://src/tests:angle_unittests/", - "use_isolated_scripts_api": true - } - ] - }, - "mac-exp-amd": { - "gtest_tests": [ - { - "args": [ - "--use-angle=gl", - "--max-processes=1" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_egl_gl_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=metal" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_egl_metal_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "angle_deqp_egl_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_egl_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=gl", - "--flaky-retries=2" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_gles2_gl_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=metal", - "--flaky-retries=2" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_gles2_metal_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "angle_deqp_gles2_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles2_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=gl", - "--flaky-retries=2" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_gles3_gl_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--use-angle=metal", - "--flaky-retries=2" - ], - "merge": { - "script": "//scripts/angle_deqp_test_merge.py" - }, - "name": "angle_deqp_gles3_metal_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "angle_deqp_gles3_tests", - "test_id_prefix": "ninja://src/tests:angle_deqp_gles3_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ - "--gtest_filter=-*Vulkan_SwiftShader*", - "--flaky-retries=2" - ], - "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "angle_end2end_tests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", - "pool": "chromium.tests.gpu" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 2 - }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://src/tests:angle_end2end_tests/", - "use_isolated_scripts_api": true - }, - { - "merge": { - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "angle_unittests", - "swarming": { - "containment_type": "AUTO", - "dimensions": { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:67ef", - "hidpi": "1", - "os": "Mac-14.3.1|Mac-14.4.1", + "os": "Mac-14.4.1", "pool": "chromium.tests.gpu" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -6027,6 +5825,7 @@ } ] }, + "mac-exp-amd": {}, "mac-exp-intel": {}, "mac-exp-nvidia": {}, "mac-intel": { diff --git a/infra/specs/angle_mb_config.pyl b/infra/specs/angle_mb_config.pyl index c211e7ee34..c2bbe79f0e 100644 --- a/infra/specs/angle_mb_config.pyl +++ b/infra/specs/angle_mb_config.pyl @@ -60,10 +60,10 @@ 'configs': { 'angle_asan_bot': ['angle', 'opencl', 'reclient', 'asan', 'release', 'desktop'], 'angle_asan_lsan_ubsan_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'asan', 'lsan', 'ubsan', 'release', 'desktop'], - 'angle_non_clang_debug_bot': ['angle', 'opencl', 'non_clang', 'debug', 'desktop'], - 'angle_non_clang_release_bot': ['angle', 'opencl', 'non_clang', 'release', 'desktop'], - 'angle_non_clang_x86_debug_bot': ['angle', 'opencl', 'non_clang', 'x86', 'debug'], - 'angle_non_clang_x86_release_bot': ['angle', 'opencl', 'non_clang', 'x86', 'release'], + 'angle_non_clang_debug_bot': ['angle', 'non_clang', 'debug', 'desktop'], + 'angle_non_clang_release_bot': ['angle', 'non_clang', 'release', 'desktop'], + 'angle_non_clang_x86_debug_bot': ['angle', 'non_clang', 'x86', 'debug', 'cxx17'], + 'angle_non_clang_x86_release_bot': ['angle', 'non_clang', 'x86', 'release'], 'angle_reclient_android_arm64_debug_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'android', 'arm64', 'debug'], 'angle_reclient_android_arm64_release_bot': ['angle', 'capture', 'opencl', 'openclcts', 'reclient', 'android', 'arm64', 'release'], 'angle_reclient_android_arm_debug_bot': ['angle', 'opencl', 'openclcts', 'reclient', 'android', 'arm', 'debug', 'cxx17'], diff --git a/infra/specs/mixins.pyl b/infra/specs/mixins.pyl index 949a6270cf..e1bead1e5a 100644 --- a/infra/specs/mixins.pyl +++ b/infra/specs/mixins.pyl @@ -63,13 +63,13 @@ 'display_attached': '1', 'gpu': '1002:67ef', 'hidpi': '1', - 'os': 'Mac-14.3.1|Mac-14.4.1', + 'os': 'Mac-14.4.1', 'pool': 'chromium.tests.gpu'}}}, 'mac_retina_amd_gpu_stable': { 'swarming': { 'dimensions': { 'cpu': 'x86-64', 'display_attached': '1', 'gpu': '1002:67ef', 'hidpi': '1', - 'os': 'Mac-13.5', + 'os': 'Mac-14.4.1', 'pool': 'chromium.tests.gpu'}}}, 'mac_retina_nvidia_gpu_experimental': { 'swarming': { 'dimensions': { 'cpu': 'x86-64', 'display_attached': '1', diff --git a/infra/specs/waterfalls.pyl b/infra/specs/waterfalls.pyl index d3ba3786ec..a9c072ecf8 100644 --- a/infra/specs/waterfalls.pyl +++ b/infra/specs/waterfalls.pyl @@ -230,7 +230,6 @@ 'mac_retina_amd_gpu_experimental', ], 'test_suites': { - 'gtest_tests': 'mac_amd_and_intel_gtests', }, }, 'mac-exp-intel': { diff --git a/scripts/code_generation_hashes/Extension_files.json b/scripts/code_generation_hashes/Extension_files.json index 6df352232c..dd6a1fa484 100644 --- a/scripts/code_generation_hashes/Extension_files.json +++ b/scripts/code_generation_hashes/Extension_files.json @@ -2,7 +2,7 @@ "doc/ExtensionSupport.md": "a139fa98744132d92c5d66356efc373d", "scripts/egl_angle_ext.xml": - "697a927b35f5f48c6a1be5cf56e9f103", + "bdd2dcfaa4b6d82e12b6004f1435946d", "scripts/extension_data/intel_630_linux.json": "3b86832de6a7095f4617e273cba6d45e", "scripts/extension_data/intel_630_win10.json": @@ -22,7 +22,7 @@ "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "src/libANGLE/gen_extensions.py": "6ea1cb1733c4df98b527bbf2752e118b", "src/libANGLE/gles_extensions_autogen.cpp": diff --git a/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json b/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json index 8287da966b..c7b88bb0e7 100644 --- a/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json +++ b/scripts/code_generation_hashes/GL_CTS_(dEQP)_build_files.json @@ -26,11 +26,11 @@ "third_party/VK-GL-CTS/src/external/openglcts/modules/CMakeLists.txt": "51bab42277ace2f99407b1b88715a92f", "third_party/VK-GL-CTS/src/external/openglcts/modules/common/CMakeLists.txt": - "7662b4a17b08f07b4b2e2a57edceb209", + "38908cad976953ed99c59b6b1ba61a87", "third_party/VK-GL-CTS/src/external/openglcts/modules/common/subgroups/CMakeLists.txt": "bf71ce2d9756ccee7833a789737e6481", "third_party/VK-GL-CTS/src/external/openglcts/modules/gl/CMakeLists.txt": - "0f90224dc01d52e436014cf5f0b14490", + "143dffb11c57e173f8f73966466c4de9", "third_party/VK-GL-CTS/src/external/openglcts/modules/gles2/CMakeLists.txt": "5ac63dce60849bf12e3ab2dde99424ab", "third_party/VK-GL-CTS/src/external/openglcts/modules/gles3/CMakeLists.txt": @@ -70,7 +70,7 @@ "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/device_group/CMakeLists.txt": "451a6c35fd38aec3212d02f14f201cf9", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/draw/CMakeLists.txt": - "b38e8a3627004e3556ea88df76bdb088", + "11c790826f72087412af6e0b19ab30b3", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/dynamic_state/CMakeLists.txt": "3db8818671533ace06b9b7710aeda461", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/fragment_ops/CMakeLists.txt": @@ -128,7 +128,7 @@ "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/sparse_resources/CMakeLists.txt": "0d64de8230844f6dfd44306993105f31", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt": - "672bde36c1263be73ba59503021410d9", + "45857ee5183883971f8d53949f8d06b8", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/ssbo/CMakeLists.txt": "509295d2d41e74dc371ec29b221ee854", "third_party/VK-GL-CTS/src/external/vulkancts/modules/vulkan/subgroups/CMakeLists.txt": diff --git a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json index d98a7ff66e..1ffbd3d64e 100644 --- a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json +++ b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json @@ -1,12 +1,12 @@ { "scripts/egl_angle_ext.xml": - "697a927b35f5f48c6a1be5cf56e9f103", + "bdd2dcfaa4b6d82e12b6004f1435946d", "scripts/generate_loader.py": "93c78a8d11323fa311fed5118fbcf083", "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "src/libEGL/egl_loader_autogen.cpp": "9ed54b9c0801cbe9b81746e79baa09bd", "src/libEGL/egl_loader_autogen.h": diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json index e4eca7e117..58dcbccfbc 100644 --- a/scripts/code_generation_hashes/GL_EGL_entry_points.json +++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json @@ -1,16 +1,16 @@ { "scripts/egl_angle_ext.xml": - "697a927b35f5f48c6a1be5cf56e9f103", + "bdd2dcfaa4b6d82e12b6004f1435946d", "scripts/entry_point_packed_egl_enums.json": "a72ae855c6b403912103b519139951a1", "scripts/entry_point_packed_gl_enums.json": "57a3a729fd25032bc336f4b6a55bc238", "scripts/generate_entry_points.py": - "7e554c0ecbbe527501e083b9e0f720b7", + "bbb6454f5e67df1f24ed71aa86d26c63", "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "src/common/entry_points_enum_autogen.cpp": "96fad45d19b9fe517fff0ca858a92eff", "src/common/entry_points_enum_autogen.h": @@ -158,7 +158,7 @@ "src/libGLESv2/entry_points_gles_1_0_autogen.h": "1d3aef77845a416497070985a8e9cb31", "src/libGLESv2/entry_points_gles_2_0_autogen.cpp": - "19c044201387796e546be26bb554ac48", + "a1a5a13754a2720df59375292039abc3", "src/libGLESv2/entry_points_gles_2_0_autogen.h": "691c60c2dfed9beca68aa1f32aa2c71b", "src/libGLESv2/entry_points_gles_3_0_autogen.cpp": diff --git a/scripts/code_generation_hashes/GLenum_value_to_string_map.json b/scripts/code_generation_hashes/GLenum_value_to_string_map.json index 5512923268..85e351f3dc 100644 --- a/scripts/code_generation_hashes/GLenum_value_to_string_map.json +++ b/scripts/code_generation_hashes/GLenum_value_to_string_map.json @@ -4,7 +4,7 @@ "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "src/common/gl_enum_utils_autogen.cpp": "745c4be051eb3d9c93c2116180afb3ca", "src/common/gl_enum_utils_autogen.h": diff --git a/scripts/code_generation_hashes/SPIR-V_helpers.json b/scripts/code_generation_hashes/SPIR-V_helpers.json index 944cf1a2cb..29897bad21 100644 --- a/scripts/code_generation_hashes/SPIR-V_helpers.json +++ b/scripts/code_generation_hashes/SPIR-V_helpers.json @@ -1,14 +1,14 @@ { "src/common/spirv/gen_spirv_builder_and_parser.py": - "868a697edbc38c95e36be54cf5c71435", + "771d70f2fe4c89f325cd22efd0ba9be7", "src/common/spirv/spirv_instruction_builder_autogen.cpp": - "c149de371bcd571bd31cc8eb1e517910", + "682111aced9eab0828dcb361d6f27b60", "src/common/spirv/spirv_instruction_builder_autogen.h": - "56b1309d8afabb2b64d7e16f0c4a4898", + "7451dcdf46772d43a6509e4a15d07d80", "src/common/spirv/spirv_instruction_parser_autogen.cpp": "388f17f462daa8e091238b4d1fd42ef5", "src/common/spirv/spirv_instruction_parser_autogen.h": "58282734b793c994dbe52c3aa988e40e", - "third_party/vulkan-deps/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json": + "third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json": "a8c4239344b2fc10bfc4ace7ddee1867" } diff --git a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json index f61e921dff..5811352d5d 100644 --- a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json +++ b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json @@ -2,13 +2,13 @@ "src/libANGLE/renderer/angle_format.py": "8269a72cc5629fb2544975b6c36c2bd4", "src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py": - "ffb3d44c853669c2c260b96b3808fcf3", + "a9fd6f3ff2b584aff382364489146c76", "src/libANGLE/renderer/vulkan/vk_format_map.json": "096290d605cbed91ccef9a81bab31984", "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_data.json": "fa2bd54c1bb0ab2cf1d386061a4bc5c5", "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp": "96ac9e08704b7a086f7c8db5d213de2b", - "third_party/vulkan-deps/vulkan-headers/src/registry/vk.xml": + "third_party/vulkan-headers/src/registry/vk.xml": "c63dc0947e72e4b6ee50b5c86c728903" } diff --git a/scripts/code_generation_hashes/interpreter_utils.json b/scripts/code_generation_hashes/interpreter_utils.json index e6ab7a7b7c..1aef4af6e1 100644 --- a/scripts/code_generation_hashes/interpreter_utils.json +++ b/scripts/code_generation_hashes/interpreter_utils.json @@ -1,12 +1,12 @@ { "scripts/egl_angle_ext.xml": - "697a927b35f5f48c6a1be5cf56e9f103", + "bdd2dcfaa4b6d82e12b6004f1435946d", "scripts/gen_interpreter_utils.py": "10ba16ee78604763fc883525dd275de8", "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "third_party/EGL-Registry/src/api/egl.xml": "2056d54ea07156f1988ca1366bdee21a", "third_party/OpenCL-Docs/src/xml/cl.xml": diff --git a/scripts/code_generation_hashes/proc_table.json b/scripts/code_generation_hashes/proc_table.json index ee818513f3..49f20ffd85 100644 --- a/scripts/code_generation_hashes/proc_table.json +++ b/scripts/code_generation_hashes/proc_table.json @@ -1,12 +1,12 @@ { "scripts/egl_angle_ext.xml": - "697a927b35f5f48c6a1be5cf56e9f103", + "bdd2dcfaa4b6d82e12b6004f1435946d", "scripts/gen_proc_table.py": "073351265b085943f816498cecaa281c", "scripts/gl_angle_ext.xml": "197e07a917d5bba6dfa2840fb1b58e7e", "scripts/registry_xml.py": - "eb23ab1ec2c7c8d78aefbfe0aa86fc4a", + "0d9085b06bc29cf8fdfb2a04a24a44c2", "src/libGLESv2/proc_table_cl_autogen.cpp": "ed003b0f041aaaa35b67d3fe07e61f91", "src/libGLESv2/proc_table_egl_autogen.cpp": diff --git a/scripts/egl_angle_ext.xml b/scripts/egl_angle_ext.xml index e323cb717a..4431493a2a 100644 --- a/scripts/egl_angle_ext.xml +++ b/scripts/egl_angle_ext.xml @@ -302,6 +302,16 @@ <enum name="EGL_CGL_PIXEL_FORMAT_ANGLE"/> </require> </extension> + <extension name="EGL_ANGLE_device_d3d9" supported="egl"> + <require> + <enum name="EGL_D3D9_DEVICE_ANGLE"/> + </require> + </extension> + <extension name="EGL_ANGLE_device_d3d1" supported="egl"> + <require> + <enum name="EGL_D3D11_DEVICE_ANGLE"/> + </require> + </extension> <extension name="EGL_ANGLE_device_eagl" supported="egl"> <require> <enum name="EGL_EAGL_CONTEXT_ANGLE"/> diff --git a/scripts/export_targets.py b/scripts/export_targets.py index 5a06940715..bd2f5e2e6c 100755 --- a/scripts/export_targets.py +++ b/scripts/export_targets.py @@ -194,8 +194,8 @@ IGNORED_INCLUDES = { b'dirent_on_windows.h', b'dlopen_fuchsia.h', b'kernel/image.h', + b'libANGLE/renderer/d3d/d3d11/Device11.h', b'libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h', - b'libANGLE/renderer/d3d/DeviceD3D.h', b'libANGLE/renderer/d3d/DisplayD3D.h', b'libANGLE/renderer/d3d/RenderTargetD3D.h', b'libANGLE/renderer/gl/cgl/DisplayCGL.h', diff --git a/scripts/generate_android_bp.py b/scripts/generate_android_bp.py index bd17c15178..16d2ae844e 100644 --- a/scripts/generate_android_bp.py +++ b/scripts/generate_android_bp.py @@ -200,14 +200,22 @@ target_blockist = [ third_party_target_allowlist = [ '//third_party/abseil-cpp', - '//third_party/vulkan-deps', + '//third_party/glslang/src', + '//third_party/spirv-cross/src', + '//third_party/spirv-headers/src', + '//third_party/spirv-tools/src', + '//third_party/vulkan-headers/src', + '//third_party/vulkan-loader/src', + '//third_party/vulkan-tools/src', + '//third_party/vulkan-utility-libraries/src', + '//third_party/vulkan-validation-layers/src', '//third_party/vulkan_memory_allocator', ] include_blocklist = [ '//buildtools/third_party/libc++/', '//third_party/libc++/src/', - '//out/Android/gen/third_party/vulkan-deps/glslang/src/include/', + '//out/Android/gen/third_party/glslang/src/include/', '//third_party/zlib/', '//third_party/zlib/google/', ] @@ -391,10 +399,8 @@ def gn_action_args_to_blueprint_args(blueprint_inputs, blueprint_outputs, args): # path. b/150457277 remap_folders = [ # Specific special-cases first, since the other will strip the prefixes. - ('gen/third_party/vulkan-deps/glslang/src/include/glslang/build_info.h', - 'glslang/build_info.h'), - ('third_party/vulkan-deps/glslang/src', - 'external/angle/third_party/vulkan-deps/glslang/src'), + ('gen/third_party/glslang/src/include/glslang/build_info.h', 'glslang/build_info.h'), + ('third_party/glslang/src', 'external/angle/third_party/glslang/src'), ('../../', ''), ('gen/', ''), ] @@ -696,16 +702,15 @@ def main(): 'third_party/proguard/LICENSE', 'third_party/r8/LICENSE', 'third_party/turbine/LICENSE', - 'third_party/vulkan-deps/glslang/LICENSE', - 'third_party/vulkan-deps/glslang/src/LICENSE.txt', - 'third_party/vulkan-deps/LICENSE', - 'third_party/vulkan-deps/spirv-headers/LICENSE', - 'third_party/vulkan-deps/spirv-headers/src/LICENSE', - 'third_party/vulkan-deps/spirv-tools/LICENSE', - 'third_party/vulkan-deps/spirv-tools/src/LICENSE', - 'third_party/vulkan-deps/spirv-tools/src/utils/vscode/src/lsp/LICENSE', - 'third_party/vulkan-deps/vulkan-headers/LICENSE.txt', - 'third_party/vulkan-deps/vulkan-headers/src/LICENSE.md', + 'third_party/glslang/LICENSE', + 'third_party/glslang/src/LICENSE.txt', + 'third_party/spirv-headers/LICENSE', + 'third_party/spirv-headers/src/LICENSE', + 'third_party/spirv-tools/LICENSE', + 'third_party/spirv-tools/src/LICENSE', + 'third_party/spirv-tools/src/utils/vscode/src/lsp/LICENSE', + 'third_party/vulkan-headers/LICENSE.txt', + 'third_party/vulkan-headers/src/LICENSE.md', 'third_party/vulkan_memory_allocator/LICENSE.txt', 'tools/flex-bison/third_party/m4sugar/LICENSE', 'tools/flex-bison/third_party/skeletons/LICENSE', diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py index 0bf5224fa2..35dca1a1cb 100755 --- a/scripts/generate_entry_points.py +++ b/scripts/generate_entry_points.py @@ -3095,6 +3095,15 @@ def get_context_lock(api, cmd_name): if api == apis.GLES and cmd_name.startswith("glEGLImage"): return "SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked);" + # The following commands do not need to hold the share group lock. Both + # validation and their implementation in the context are limited to + # context-local state. + # + # - glBindBuffer: This function looks up the ID in the buffer manager, + # access to which is thread-safe for buffers. + if cmd_name in ['glBindBuffer']: + return "" + return "SCOPED_SHARE_CONTEXT_LOCK(context);" diff --git a/scripts/registry_xml.py b/scripts/registry_xml.py index ed55ba4ec9..b6e096aab8 100644 --- a/scripts/registry_xml.py +++ b/scripts/registry_xml.py @@ -322,6 +322,8 @@ supported_egl_extensions = [ "EGL_ANGLE_d3d_share_handle_client_buffer", "EGL_ANGLE_device_creation", "EGL_ANGLE_device_d3d", + "EGL_ANGLE_device_d3d11", + "EGL_ANGLE_device_d3d9", "EGL_ANGLE_display_semaphore_share_group", "EGL_ANGLE_display_texture_share_group", "EGL_ANGLE_external_context_and_surface", diff --git a/scripts/roll_aosp.sh b/scripts/roll_aosp.sh index 8170f3eaf5..32c8bb4be9 100755 --- a/scripts/roll_aosp.sh +++ b/scripts/roll_aosp.sh @@ -115,10 +115,10 @@ export PATH=`pwd`/${DEPOT_TOOLS_DIR}:$PATH third_party_deps=( "build" "third_party/abseil-cpp" - "third_party/vulkan-deps/glslang/src" - "third_party/vulkan-deps/spirv-headers/src" - "third_party/vulkan-deps/spirv-tools/src" - "third_party/vulkan-deps/vulkan-headers/src" + "third_party/glslang/src" + "third_party/spirv-headers/src" + "third_party/spirv-tools/src" + "third_party/vulkan-headers/src" "third_party/vulkan_memory_allocator" ) @@ -127,9 +127,7 @@ root_add_deps=( "third_party" ) -# Only add the parts of NDK and vulkan-deps that are required by ANGLE. The entire dep is too large. delete_only_deps=( - "third_party/vulkan-deps" "third_party/zlib" # Replaced by Android's zlib; delete for gclient to work https://crbug.com/skia/14155#c3 ) @@ -192,10 +190,10 @@ extra_removal_files=( # Remove Android.mk files to prevent automated CLs: # "[LSC] Add LOCAL_LICENSE_KINDS to external/angle" "Android.mk" - "third_party/vulkan-deps/glslang/src/Android.mk" - "third_party/vulkan-deps/glslang/src/ndk_test/Android.mk" - "third_party/vulkan-deps/spirv-tools/src/Android.mk" - "third_party/vulkan-deps/spirv-tools/src/android_test/Android.mk" + "third_party/glslang/src/Android.mk" + "third_party/glslang/src/ndk_test/Android.mk" + "third_party/spirv-tools/src/Android.mk" + "third_party/spirv-tools/src/android_test/Android.mk" "third_party/siso" # Not needed ) diff --git a/src/common/PackedEnums.h b/src/common/PackedEnums.h index 006367b2f7..4a7f34778f 100644 --- a/src/common/PackedEnums.h +++ b/src/common/PackedEnums.h @@ -784,12 +784,6 @@ typename std::enable_if<IsResourceIDType<T>::value, bool>::type operator<(const template <typename ResourceIDType> GLuint GetIDValue(ResourceIDType id); -template <> -inline GLuint GetIDValue(GLuint id) -{ - return id; -} - template <typename ResourceIDType> inline GLuint GetIDValue(ResourceIDType id) { diff --git a/src/common/SimpleMutex.h b/src/common/SimpleMutex.h index 5d3c30cb93..84ffa1a1da 100644 --- a/src/common/SimpleMutex.h +++ b/src/common/SimpleMutex.h @@ -132,6 +132,13 @@ using SimpleMutex = priv::MutexOnFutex; using SimpleMutex = priv::MutexOnStd; #endif +// A no-op mutex to replace SimpleMutex where a lock is not needed. +struct NoOpMutex +{ + void lock() {} + void unlock() {} + bool try_lock() { return true; } +}; } // namespace angle #endif // COMMON_SIMPLEMUTEX_H_ diff --git a/src/common/SimpleMutex_unittest.cpp b/src/common/SimpleMutex_unittest.cpp index 72db80a06b..ec8a52d1ac 100644 --- a/src/common/SimpleMutex_unittest.cpp +++ b/src/common/SimpleMutex_unittest.cpp @@ -15,12 +15,6 @@ namespace angle { namespace { -struct NoOpMutex -{ - void lock() {} - void unlock() {} -}; - template <typename TestMutex> bool runBasicMutexTest() { diff --git a/src/common/mathutil.cpp b/src/common/mathutil.cpp index 5cbc6a920a..630348923b 100644 --- a/src/common/mathutil.cpp +++ b/src/common/mathutil.cpp @@ -50,7 +50,7 @@ unsigned int convertRGBFloatsTo999E5(float red, float green, float blue) const float green_c = std::max<float>(0, std::min(g_sharedexp_max, green)); const float blue_c = std::max<float>(0, std::min(g_sharedexp_max, blue)); - const float max_c = std::max<float>(std::max<float>(red_c, green_c), blue_c); + const float max_c = std::max<float>({red_c, green_c, blue_c}); const float exp_p = std::max<float>(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias; const int max_s = static_cast<int>( diff --git a/src/common/spirv/gen_spirv_builder_and_parser.py b/src/common/spirv/gen_spirv_builder_and_parser.py index c7e1f401b3..01335a026f 100755 --- a/src/common/spirv/gen_spirv_builder_and_parser.py +++ b/src/common/spirv/gen_spirv_builder_and_parser.py @@ -13,10 +13,10 @@ import os import sys # ANGLE uses SPIR-V 1.0 currently, so there's no reason to generate code for newer instructions. -SPIRV_GRAMMAR_FILE = '../../../third_party/vulkan-deps/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json' +SPIRV_GRAMMAR_FILE = '../../../third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json' # Cherry pick some extra extensions from here that aren't in SPIR-V 1.0. -SPIRV_CHERRY_PICKED_EXTENSIONS_FILE = '../../../third_party/vulkan-deps/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json' +SPIRV_CHERRY_PICKED_EXTENSIONS_FILE = '../../../third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json' # The script has two sets of outputs, a header and source file for SPIR-V code generation, and a # header and source file for SPIR-V parsing. @@ -106,12 +106,12 @@ uint32_t MakeLengthOp(size_t length, spv::Op op) } } // anonymous namespace -void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount) +void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount) { // Header: // // - Magic number - // - Version (1.0) + // - Version (1.X) // - ANGLE's Generator number: // * 24 for tool id (higher 16 bits) // * 1 for tool version (lower 16 bits)) @@ -123,7 +123,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount) ASSERT(blob->empty()); blob->push_back(spv::MagicNumber); - blob->push_back(0x00010000); + blob->push_back(version); blob->push_back(kANGLEGeneratorId << 16 | kANGLEGeneratorVersion); blob->push_back(idCount); blob->push_back(0x00000000); @@ -131,7 +131,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount) """ BUILDER_HELPER_FUNCTION_PROTOTYPE = """ - void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount); + void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount); """ PARSER_FIXED_FUNCTIONS_PROTOTYPES = """void GetInstructionOpAndLength(const uint32_t *_instruction, diff --git a/src/common/spirv/spirv_instruction_builder_autogen.cpp b/src/common/spirv/spirv_instruction_builder_autogen.cpp index 6e6ad6f510..c63aed55c3 100644 --- a/src/common/spirv/spirv_instruction_builder_autogen.cpp +++ b/src/common/spirv/spirv_instruction_builder_autogen.cpp @@ -38,12 +38,12 @@ uint32_t MakeLengthOp(size_t length, spv::Op op) } } // anonymous namespace -void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount) +void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount) { // Header: // // - Magic number - // - Version (1.0) + // - Version (1.X) // - ANGLE's Generator number: // * 24 for tool id (higher 16 bits) // * 1 for tool version (lower 16 bits)) @@ -55,7 +55,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount) ASSERT(blob->empty()); blob->push_back(spv::MagicNumber); - blob->push_back(0x00010000); + blob->push_back(version); blob->push_back(kANGLEGeneratorId << 16 | kANGLEGeneratorVersion); blob->push_back(idCount); blob->push_back(0x00000000); diff --git a/src/common/spirv/spirv_instruction_builder_autogen.h b/src/common/spirv/spirv_instruction_builder_autogen.h index 1caf5cd204..7ecfd0a1ce 100644 --- a/src/common/spirv/spirv_instruction_builder_autogen.h +++ b/src/common/spirv/spirv_instruction_builder_autogen.h @@ -20,7 +20,7 @@ namespace angle namespace spirv { -void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount); +void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount); void WriteNop(Blob *blob); void WriteUndef(Blob *blob, IdResultType idResultType, IdResult idResult); void WriteSourceContinued(Blob *blob, LiteralString continuedSource); diff --git a/src/common/spirv/spirv_types.h b/src/common/spirv/spirv_types.h index c97e4db477..b27befdbaa 100644 --- a/src/common/spirv/spirv_types.h +++ b/src/common/spirv/spirv_types.h @@ -125,6 +125,11 @@ enum HeaderIndex kHeaderIndexInstructions = 5, }; +// SPIR-V version +constexpr uint32_t kVersion_1_0 = 0x00010000; +constexpr uint32_t kVersion_1_3 = 0x00010300; +constexpr uint32_t kVersion_1_4 = 0x00010400; + // Returns whether SPIR-V is valid. Useful for ASSERTs. Automatically generates a warning if // SPIR-V is not valid. bool Validate(const Blob &blob); diff --git a/src/compiler/translator/hlsl/ResourcesHLSL.h b/src/compiler/translator/hlsl/ResourcesHLSL.h index d5842a3d57..9541c9d923 100644 --- a/src/compiler/translator/hlsl/ResourcesHLSL.h +++ b/src/compiler/translator/hlsl/ResourcesHLSL.h @@ -147,8 +147,8 @@ class ResourcesHLSL : angle::NonCopyable std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap; std::map<std::string, unsigned int> mUniformRegisterMap; std::map<std::string, bool> mUniformBlockUseStructuredBufferMap; - unsigned int mReadonlyImage2DRegisterIndex; - unsigned int mImage2DRegisterIndex; + unsigned int mReadonlyImage2DRegisterIndex = 0; + unsigned int mImage2DRegisterIndex = 0; }; } // namespace sh diff --git a/src/compiler/translator/msl/IdGen.cpp b/src/compiler/translator/msl/IdGen.cpp index b74e71bdd9..88435df198 100644 --- a/src/compiler/translator/msl/IdGen.cpp +++ b/src/compiler/translator/msl/IdGen.cpp @@ -31,10 +31,6 @@ Name IdGen::createNewName(size_t count, mNewNameBuffer += '_'; mNewNameBuffer += idBuffer; - // Note: - // Double underscores are only allowed in C++ (and thus Metal) vendor identifiers, so here we - // take care not to introduce any. - for (size_t i = 0; i < count; ++i) { const ImmutableString baseName = toImmutable(baseNames[i]); @@ -43,19 +39,15 @@ Name IdGen::createNewName(size_t count, const char *base = baseName.data(); if (baseName.beginsWith(kAngleInternalPrefix)) { + // skip 'ANGLE' or 'ANGLE_' prefix base += sizeof(kAngleInternalPrefix) - 1; - } - if (*base == '_') - { - ++base; - } - ASSERT(*base != '_'); - - if (mNewNameBuffer.back() != '_') - { - mNewNameBuffer += '_'; + if (*base == '_') + { + ++base; + } } + mNewNameBuffer += '_'; mNewNameBuffer += base; } } diff --git a/src/compiler/translator/spirv/BuildSPIRV.cpp b/src/compiler/translator/spirv/BuildSPIRV.cpp index 8edf4bb11b..b79b99b291 100644 --- a/src/compiler/translator/spirv/BuildSPIRV.cpp +++ b/src/compiler/translator/spirv/BuildSPIRV.cpp @@ -2321,7 +2321,7 @@ spirv::Blob SPIRVBuilder::getSpirv() mSpirvFunctions.size()); // Generate the SPIR-V header. - spirv::WriteSpirvHeader(&result, mNextAvailableId); + spirv::WriteSpirvHeader(&result, spirv::kVersion_1_0, mNextAvailableId); // Generate metadata in the following order: // diff --git a/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp b/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp index a3dc0567a6..49eaec47c3 100644 --- a/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp +++ b/src/compiler/translator/tree_ops/msl/SeparateCompoundExpressions.cpp @@ -635,7 +635,7 @@ class Separator : public TIntermRebuild PostResult visitConstantUnionPost(TIntermConstantUnion &node) override { const TType &type = node.getType(); - if (!type.isScalar()) + if (!type.isScalar() && !type.isVector() && !type.isMatrix()) { pushBinding(node, node); } diff --git a/src/image_util/loadimage_etc.cpp b/src/image_util/loadimage_etc.cpp index 16737501ba..b517899296 100644 --- a/src/image_util/loadimage_etc.cpp +++ b/src/image_util/loadimage_etc.cpp @@ -1141,7 +1141,7 @@ struct ETC2Block // From the eigenvalue and eigenvector, choose the axis to project // colors on. When projecting colors we want to do integer computations // for speed, so we normalize the eigenvector to the [0, 512] range. - float magn = std::max(std::max(std::abs(vfr), std::abs(vfg)), std::abs(vfb)); + float magn = std::max({std::abs(vfr), std::abs(vfg), std::abs(vfb)}); magn = kQuantizeRange / magn; vr = static_cast<int>(vfr * magn); vg = static_cast<int>(vfg * magn); diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp index 876b1921c4..43452e79cb 100644 --- a/src/libANGLE/Buffer.cpp +++ b/src/libANGLE/Buffer.cpp @@ -67,6 +67,13 @@ void Buffer::onDestroy(const Context *context) void Buffer::onBind(const Context *context, BufferBinding target) { + // Note: this function is called from glBindBuffer, which does not hold the share group lock. + // However, it only affects webgl contexts, where browsers already guarantees thread safety. + if (!context->isWebGL()) + { + return; + } + if (mState.mWebGLType == WebGLBufferType::Undefined) { if (target == BufferBinding::ElementArray) diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h index 61c7fb3a75..507f6c333a 100644 --- a/src/libANGLE/Buffer.h +++ b/src/libANGLE/Buffer.h @@ -93,7 +93,7 @@ ANGLE_INLINE bool operator==(const ContentsObserver &lhs, const ContentsObserver return lhs.bufferIndex == rhs.bufferIndex && lhs.observer == rhs.observer; } -class Buffer final : public RefCountObject<BufferID>, +class Buffer final : public ThreadSafeRefCountObject<BufferID>, public LabeledObject, public angle::ObserverInterface, public angle::Subject diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp index 659be9a991..5e04cc8de5 100644 --- a/src/libANGLE/Caps.cpp +++ b/src/libANGLE/Caps.cpp @@ -1361,6 +1361,8 @@ std::vector<std::string> DeviceExtensions::getStrings() const // clang-format off // | Extension name | Supported flag | Output vector | InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_d3d9", deviceD3D9, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_d3d11", deviceD3D11, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_eagl", deviceEAGL, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_metal", deviceMetal, &extensionStrings); diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h index 5cfe3a88bd..c8b1722e51 100644 --- a/src/libANGLE/Caps.h +++ b/src/libANGLE/Caps.h @@ -700,6 +700,12 @@ struct DeviceExtensions // EGL_ANGLE_device_d3d bool deviceD3D = false; + // EGL_ANGLE_device_d3d9 + bool deviceD3D9 = false; + + // EGL_ANGLE_device_d3d11 + bool deviceD3D11 = false; + // EGL_ANGLE_device_cgl bool deviceCGL = false; diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp index 5eda734ca6..77f4bd999e 100644 --- a/src/libANGLE/Context.cpp +++ b/src/libANGLE/Context.cpp @@ -664,7 +664,21 @@ Context::Context(egl::Display *display, egl::Error Context::initialize() { if (!mImplementation) + { return egl::Error(EGL_NOT_INITIALIZED, "native context creation failed"); + } + + // If the final context version created (with backwards compatibility possibly added in), + // generate an error if it's higher than the maximum supported version for the display. This + // validation is always done even with EGL validation disabled because it's not possible to + // detect ahead of time if an ES 3.1 context is supported (no ES_31_BIT) or if + // KHR_no_config_context is used. + if (getClientType() == EGL_OPENGL_ES_API && + getClientVersion() > getDisplay()->getMaxSupportedESVersion()) + { + return egl::Error(EGL_BAD_ATTRIBUTE, "Requested version is not supported"); + } + return egl::NoError(); } diff --git a/src/libANGLE/Device.cpp b/src/libANGLE/Device.cpp index 5acb3b56f3..ab509174be 100644 --- a/src/libANGLE/Device.cpp +++ b/src/libANGLE/Device.cpp @@ -20,7 +20,7 @@ #include "libANGLE/renderer/DeviceImpl.h" #if defined(ANGLE_ENABLE_D3D11) -# include "libANGLE/renderer/d3d/DeviceD3D.h" +# include "libANGLE/renderer/d3d/d3d11/Device11.h" #endif namespace egl @@ -54,7 +54,7 @@ egl::Error Device::CreateDevice(EGLint deviceType, void *nativeDevice, Device ** #if defined(ANGLE_ENABLE_D3D11) if (deviceType == EGL_D3D11_DEVICE_ANGLE) { - newDeviceImpl.reset(new rx::DeviceD3D(deviceType, nativeDevice)); + newDeviceImpl.reset(new rx::Device11(nativeDevice)); } #endif @@ -110,11 +110,6 @@ Error Device::getAttribute(EGLint attribute, EGLAttrib *value) return error; } -EGLint Device::getType() const -{ - return mImplementation.get()->getType(); -} - void Device::initDeviceExtensions() { mImplementation->generateExtensions(&mDeviceExtensions); diff --git a/src/libANGLE/Device.h b/src/libANGLE/Device.h index 51799ce867..f50667f521 100644 --- a/src/libANGLE/Device.h +++ b/src/libANGLE/Device.h @@ -34,7 +34,6 @@ class Device final : public LabeledObject, angle::NonCopyable Error getAttribute(EGLint attribute, EGLAttrib *value); Display *getOwningDisplay() const { return mOwningDisplay; } - EGLint getType() const; const DeviceExtensions &getExtensions() const; const std::string &getExtensionString() const; diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp index 9ebd571e84..1ce16e6180 100644 --- a/src/libANGLE/Display.cpp +++ b/src/libANGLE/Display.cpp @@ -244,28 +244,25 @@ rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState & { rx::DisplayImpl *impl = nullptr; - switch (eglDevice->getType()) - { #if defined(ANGLE_ENABLE_D3D11) - case EGL_D3D11_DEVICE_ANGLE: - impl = new rx::DisplayD3D(state); - break; + if (eglDevice->getExtensions().deviceD3D11) + { + impl = new rx::DisplayD3D(state); + } #endif + #if defined(ANGLE_ENABLE_D3D9) - case EGL_D3D9_DEVICE_ANGLE: - // Currently the only way to get EGLDeviceEXT representing a D3D9 device - // is to retrieve one from an already-existing EGLDisplay. - // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT, - // the already-existing display should be returned. - // Therefore this codepath to create a new display from the device - // should never be hit. - UNREACHABLE(); - break; -#endif - default: - UNREACHABLE(); - break; + if (eglDevice->getExtensions().deviceD3D9) + { + // Currently the only way to get EGLDeviceEXT representing a D3D9 device + // is to retrieve one from an already-existing EGLDisplay. + // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT, + // the already-existing display should be returned. + // Therefore this codepath to create a new display from the device + // should never be hit. + UNREACHABLE(); } +#endif ASSERT(impl != nullptr); return impl; diff --git a/src/libANGLE/ProgramExecutable.cpp b/src/libANGLE/ProgramExecutable.cpp index 6c6ce121d1..d7a06c2960 100644 --- a/src/libANGLE/ProgramExecutable.cpp +++ b/src/libANGLE/ProgramExecutable.cpp @@ -745,6 +745,14 @@ void ProgramExecutable::destroy(const Context *context) { ASSERT(mImplementation != nullptr); + for (SharedProgramExecutable &executable : mPPOProgramExecutables) + { + if (executable) + { + UninstallExecutable(context, &executable); + } + } + mImplementation->destroy(context); SafeDelete(mImplementation); } diff --git a/src/libANGLE/ProgramExecutable.h b/src/libANGLE/ProgramExecutable.h index d7a9252610..519b115f3d 100644 --- a/src/libANGLE/ProgramExecutable.h +++ b/src/libANGLE/ProgramExecutable.h @@ -993,6 +993,10 @@ class ProgramExecutable final : public angle::Subject // been modified. UniformBufferBindingArray<ProgramUniformBlockMask> mUniformBufferBindingToUniformBlocks; + // PPO only: installed executables from the programs. Note that these may be different from the + // programs' current executables, because they may have been unsuccessfully relinked. + ShaderMap<SharedProgramExecutable> mPPOProgramExecutables; + // Cache for sampler validation mutable Optional<bool> mCachedValidateSamplersResult; diff --git a/src/libANGLE/ProgramPipeline.cpp b/src/libANGLE/ProgramPipeline.cpp index 6d1e312f74..9d7cd66a6c 100644 --- a/src/libANGLE/ProgramPipeline.cpp +++ b/src/libANGLE/ProgramPipeline.cpp @@ -66,10 +66,11 @@ void ProgramPipelineState::useProgramStage(const Context *context, { mPrograms[shaderType] = shaderProgram; // Install the program executable, if not already - if (shaderProgram->getSharedExecutable().get() != mProgramExecutables[shaderType].get()) + if (shaderProgram->getSharedExecutable().get() != + mExecutable->mPPOProgramExecutables[shaderType].get()) { InstallExecutable(context, shaderProgram->getSharedExecutable(), - &mProgramExecutables[shaderType]); + &mExecutable->mPPOProgramExecutables[shaderType]); } shaderProgram->addRef(); } @@ -79,11 +80,11 @@ void ProgramPipelineState::useProgramStage(const Context *context, // given stage, it is as if the pipeline object has no programmable stage configured for the // indicated shader stage. mPrograms[shaderType] = nullptr; - UninstallExecutable(context, &mProgramExecutables[shaderType]); + UninstallExecutable(context, &mExecutable->mPPOProgramExecutables[shaderType]); } programObserverBinding->bind(mPrograms[shaderType]); - programExecutableObserverBinding->bind(mProgramExecutables[shaderType].get()); + programExecutableObserverBinding->bind(mExecutable->mPPOProgramExecutables[shaderType].get()); } void ProgramPipelineState::useProgramStages( @@ -175,14 +176,6 @@ void ProgramPipeline::onDestroy(const Context *context) getImplementation()->destroy(context); UninstallExecutable(context, &mState.mExecutable); - for (SharedProgramExecutable &executable : mState.mProgramExecutables) - { - if (executable) - { - mState.mProgramExecutablesToDiscard.emplace_back(std::move(executable)); - } - } - mState.destroyDiscardedExecutables(context); } @@ -505,10 +498,11 @@ angle::Result ProgramPipeline::link(const Context *context) mState.destroyDiscardedExecutables(context); // Make a new executable to hold the result of the link. - InstallExecutable( - context, - std::make_shared<ProgramExecutable>(context->getImplementation(), &mState.mInfoLog), - &mState.mExecutable); + SharedProgramExecutable newExecutable = + std::make_shared<ProgramExecutable>(context->getImplementation(), &mState.mInfoLog); + newExecutable->mPPOProgramExecutables = std::move(mState.mExecutable->mPPOProgramExecutables); + + InstallExecutable(context, newExecutable, &mState.mExecutable); onStateChange(angle::SubjectMessage::ProgramUnlinked); updateLinkedShaderStages(); @@ -597,7 +591,7 @@ angle::Result ProgramPipeline::link(const Context *context) } // Merge uniforms. - mState.mExecutable->copyUniformsFromProgramMap(mState.mProgramExecutables); + mState.mExecutable->copyUniformsFromProgramMap(mState.mExecutable->mPPOProgramExecutables); if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex)) { @@ -785,12 +779,12 @@ void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::Sub { ShaderType shaderType = static_cast<ShaderType>(index); ASSERT(mState.mPrograms[shaderType] != nullptr); - ASSERT(mState.mProgramExecutables[shaderType]); + ASSERT(mState.mExecutable->mPPOProgramExecutables[shaderType]); mState.mIsLinked = false; mState.mProgramExecutablesToDiscard.emplace_back( - std::move(mState.mProgramExecutables[shaderType])); - mState.mProgramExecutables[shaderType] = + std::move(mState.mExecutable->mPPOProgramExecutables[shaderType])); + mState.mExecutable->mPPOProgramExecutables[shaderType] = mState.mPrograms[shaderType]->getSharedExecutable(); break; diff --git a/src/libANGLE/ProgramPipeline.h b/src/libANGLE/ProgramPipeline.h index 2425e587ef..35d07552c8 100644 --- a/src/libANGLE/ProgramPipeline.h +++ b/src/libANGLE/ProgramPipeline.h @@ -64,7 +64,7 @@ class ProgramPipelineState final : angle::NonCopyable const Program *getShaderProgram(ShaderType shaderType) const { return mPrograms[shaderType]; } const SharedProgramExecutable &getShaderProgramExecutable(ShaderType shaderType) const { - return mProgramExecutables[shaderType]; + return mExecutable->mPPOProgramExecutables[shaderType]; } bool usesShaderProgram(ShaderProgramID program) const; @@ -90,10 +90,6 @@ class ProgramPipelineState final : angle::NonCopyable // The shader programs for each stage. ShaderMap<Program *> mPrograms; - // Installed executables from the programs. Note that these may be different from the programs' - // current executables, because they may have been unsuccessfully relinked. - ShaderMap<SharedProgramExecutable> mProgramExecutables; - // Mapping from program's UBOs into the program executable's UBOs. ShaderMap<ProgramUniformBlockArray<GLuint>> mUniformBlockMap; diff --git a/src/libANGLE/RefCountObject.h b/src/libANGLE/RefCountObject.h index d01677f58f..b01efcb336 100644 --- a/src/libANGLE/RefCountObject.h +++ b/src/libANGLE/RefCountObject.h @@ -68,12 +68,12 @@ class ThreadSafeRefCountObject : angle::NonCopyable virtual void onDestroy(const ContextType *context) {} - void addRef() const { ++mRefCount; } + void addRef() const { mRefCount.fetch_add(1, std::memory_order_relaxed); } ANGLE_INLINE void release(const ContextType *context) { ASSERT(mRefCount > 0); - if (mRefCount.fetch_sub(1) == 1) + if (mRefCount.fetch_sub(1, std::memory_order_acq_rel) == 1) { onDestroy(context); delete this; @@ -206,10 +206,11 @@ class Context; template <class ObjectType> class BindingPointer; -using RefCountObjectNoID = angle::RefCountObject<Context, angle::Result>; +using RefCountObjectNoID = angle::RefCountObject<Context, angle::Result>; +using ThreadSafeRefCountObjectNoID = angle::ThreadSafeRefCountObject<Context, angle::Result>; -template <typename IDType> -class RefCountObject : public gl::RefCountObjectNoID +template <typename IDType, typename RC = RefCountObjectNoID> +class RefCountObject : public RC { public: explicit RefCountObject(rx::UniqueSerial serial, IDType id) : mSerial(serial), mId(id) {} @@ -225,6 +226,8 @@ class RefCountObject : public gl::RefCountObjectNoID rx::UniqueSerial mSerial; IDType mId; }; +template <typename IDType> +using ThreadSafeRefCountObject = RefCountObject<IDType, ThreadSafeRefCountObjectNoID>; template <class ObjectType> class BindingPointer : public angle::BindingPointer<ObjectType, Context> diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp index bf0c93d59e..60a1be10f6 100644 --- a/src/libANGLE/ResourceManager.cpp +++ b/src/libANGLE/ResourceManager.cpp @@ -61,7 +61,8 @@ void ResourceManagerBase::release(const Context *context) template <typename ResourceType, typename ImplT, typename IDType> TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager() { - ASSERT(UnsafeResourceMapIter(mObjectMap).empty()); + using UnsafeResourceMapIterTyped = UnsafeResourceMapIter<ResourceType, IDType>; + ASSERT(UnsafeResourceMapIterTyped(mObjectMap).empty()); } template <typename ResourceType, typename ImplT, typename IDType> diff --git a/src/libANGLE/ResourceMap.h b/src/libANGLE/ResourceMap.h index 92d6b6251d..5604cd49c9 100644 --- a/src/libANGLE/ResourceMap.h +++ b/src/libANGLE/ResourceMap.h @@ -11,10 +11,99 @@ #ifndef LIBANGLE_RESOURCE_MAP_H_ #define LIBANGLE_RESOURCE_MAP_H_ +#include <mutex> +#include <type_traits> + +#include "common/SimpleMutex.h" #include "libANGLE/angletypes.h" namespace gl { +// The resource map needs to be internally synchronized for maps that are placed in the share group +// (as opposed to being private to the context) and that are accessed without holding the share +// group lock. +#if defined(ANGLE_ENABLE_SHARE_CONTEXT_LOCK) +using ResourceMapMutex = angle::SimpleMutex; +#else +using ResourceMapMutex = angle::NoOpMutex; +#endif + +template <bool NeedsLock = true> +struct SelectResourceMapMutex +{ + using type = ResourceMapMutex; +}; + +template <> +struct SelectResourceMapMutex<false> +{ + using type = angle::NoOpMutex; +}; + +// Analysis of ANGLE's traces as well as Chrome usage reveals the following: +// +// - Buffers: Typical applications use no more than 4000 ids. Very few use over 6000. +// - Textures: Typical applications use no more than 1200 ids. Very few use over 2000. +// - Samplers: Typical applications use no more than 50 ids. Very few use over 100. +// - Shaders and Programs: Typical applications use no more than 500. Very few use over 700. +// - Sync objects: Typical applications use no more than 500. Very few use over 1500. +// +// For all the other shared types, the maximum used id is small (under 100). For +// context-private parts (such as vertex arrays and queries), the id count can be in the +// thousands. +// +// The initial size of the flat resource map is based on the above, rounded up to a multiple of +// 1536. Resource maps that need a lock (kNeedsLock == true) have the maximum flat size identical +// to initial flat size to avoid reallocation. For others, the maps start small and can grow. +template <typename IDType> +struct ResourceMapParams +{ + static constexpr size_t kInitialFlatResourcesSize = 192; + + // The following are private to the context and don't need a lock: + // + // - Vertex Array Objects + // - Framebuffer Objects + // - Transform Feedback Objects + // - Query Objects + // + // The rest of the maps need a lock. However, only a select few are currently locked as API + // relevant to the rest of the types are protected by the share group lock. As the share group + // lock is removed from more types, the resource map lock needs to be enabled for them. + static constexpr bool kNeedsLock = false; +}; +template <> +struct ResourceMapParams<BufferID> +{ + static constexpr size_t kInitialFlatResourcesSize = 6144; + static constexpr bool kNeedsLock = true; +}; +template <> +struct ResourceMapParams<TextureID> +{ + static constexpr size_t kInitialFlatResourcesSize = 1536; + static constexpr bool kNeedsLock = false; +}; +template <> +struct ResourceMapParams<ShaderProgramID> +{ + static constexpr size_t kInitialFlatResourcesSize = 1536; + static constexpr bool kNeedsLock = false; +}; +template <> +struct ResourceMapParams<SyncID> +{ + static constexpr size_t kInitialFlatResourcesSize = 1536; + static constexpr bool kNeedsLock = false; +}; +// For the purpose of unit testing, |int| is considered private (not needing lock), and +// |unsigned int| is considered shared (needing lock). +template <> +struct ResourceMapParams<unsigned int> +{ + static constexpr size_t kInitialFlatResourcesSize = 192; + static constexpr bool kNeedsLock = true; +}; template <typename ResourceType, typename IDType> class ResourceMap final : angle::NonCopyable @@ -26,11 +115,18 @@ class ResourceMap final : angle::NonCopyable ANGLE_INLINE ResourceType *query(IDType id) const { GLuint handle = GetIDValue(id); + // No need for a lock when accessing the flat map. Either the flat map is static, or + // locking is not needed. + static_assert(!kNeedsLock || kInitialFlatResourcesSize == kFlatResourcesLimit); + if (handle < mFlatResourcesSize) { ResourceType *value = mFlatResources[handle]; return (value == InvalidPointer() ? nullptr : value); } + + std::lock_guard<Mutex> lock(mMutex); + auto it = mHashedResources.find(handle); return (it == mHashedResources.end() ? nullptr : it->second); } @@ -92,20 +188,43 @@ class ResourceMap final : angle::NonCopyable static ResourceType *InvalidPointer(); static constexpr intptr_t kInvalidPointer = static_cast<intptr_t>(-1); - // Start with 32 maximum elements in the map, which can grow. - static constexpr size_t kInitialFlatResourcesSize = 0x20; + static constexpr bool kNeedsLock = ResourceMapParams<IDType>::kNeedsLock; + using Mutex = typename SelectResourceMapMutex<kNeedsLock>::type; - // Experimental testing suggests that 16k is a reasonable upper limit. - static constexpr size_t kFlatResourcesLimit = 0x4000; + static constexpr size_t kInitialFlatResourcesSize = + ResourceMapParams<IDType>::kInitialFlatResourcesSize; - // Size of one map element. - static constexpr size_t kElementSize = sizeof(ResourceType *); + // Experimental testing suggests that ~10k is a reasonable upper limit. + static constexpr size_t kFlatResourcesLimit = kNeedsLock ? kInitialFlatResourcesSize : 0x3000; + // Due to the way assign() is implemented, kFlatResourcesLimit / kInitialFlatResourcesSize must + // be a power of 2. + static_assert(kFlatResourcesLimit % kInitialFlatResourcesSize == 0); + static_assert(((kFlatResourcesLimit / kInitialFlatResourcesSize) & + (kFlatResourcesLimit / kInitialFlatResourcesSize - 1)) == 0); size_t mFlatResourcesSize; ResourceType **mFlatResources; // A map of GL objects indexed by object ID. HashMap mHashedResources; + + // mFlatResources is allocated at object creation time, with a default size of + // |kInitialFlatResourcesSize|. This is thread safe, because the allocation is done by the + // first context in the share group. The flat map is allowed to grow up to + // |kFlatResourcesLimit|, but only for maps that don't need a lock (kNeedsLock == false). + // + // For maps that don't need a lock, this mutex is a no-op. For those that do, the mutex is + // taken when allocating / deleting objects, as well as when accessing |mHashedResources|. + // Otherwise, access to the flat map (which never gets reallocated due to + // |kInitialFlatResourcesSize == kFlatResourcesLimit|) is lockless. This latter is possible + // because the application is not allowed to gen/delete and bind the same ID in different + // threads at the same time. + // + // Note that because HandleAllocator is not yet thread-safe, glGen* and glDelete* functions + // cannot be free of the share group mutex yet. To remove the share group mutex from those + // functions, likely the HandleAllocator class should be merged with this class, and the + // necessary insert/erase operations done under this same lock. + mutable Mutex mMutex; }; // A helper to retrieve the resource map iterators while being explicit that this is not thread @@ -137,13 +256,13 @@ ResourceMap<ResourceType, IDType>::ResourceMap() : mFlatResourcesSize(kInitialFlatResourcesSize), mFlatResources(new ResourceType *[kInitialFlatResourcesSize]) { - memset(mFlatResources, kInvalidPointer, mFlatResourcesSize * kElementSize); + memset(mFlatResources, kInvalidPointer, mFlatResourcesSize * sizeof(mFlatResources[0])); } template <typename ResourceType, typename IDType> ResourceMap<ResourceType, IDType>::~ResourceMap() { - ASSERT(UnsafeResourceMapIter(*this).empty()); + ASSERT(begin() == end()); delete[] mFlatResources; } @@ -153,9 +272,10 @@ ANGLE_INLINE bool ResourceMap<ResourceType, IDType>::contains(IDType id) const GLuint handle = GetIDValue(id); if (handle < mFlatResourcesSize) { - return (mFlatResources[handle] != InvalidPointer()); + return mFlatResources[handle] != InvalidPointer(); } - return (mHashedResources.find(handle) != mHashedResources.end()); + std::lock_guard<Mutex> lock(mMutex); + return mHashedResources.find(handle) != mHashedResources.end(); } template <typename ResourceType, typename IDType> @@ -174,6 +294,8 @@ bool ResourceMap<ResourceType, IDType>::erase(IDType id, ResourceType **resource } else { + std::lock_guard<Mutex> lock(mMutex); + auto it = mHashedResources.find(handle); if (it == mHashedResources.end()) { @@ -193,6 +315,9 @@ void ResourceMap<ResourceType, IDType>::assign(IDType id, ResourceType *resource { if (handle >= mFlatResourcesSize) { + // No need for a lock as the flat map never grows when locking is needed. + static_assert(!kNeedsLock || kInitialFlatResourcesSize == kFlatResourcesLimit); + // Use power-of-two. size_t newSize = mFlatResourcesSize; while (newSize <= handle) @@ -204,8 +329,8 @@ void ResourceMap<ResourceType, IDType>::assign(IDType id, ResourceType *resource mFlatResources = new ResourceType *[newSize]; memset(&mFlatResources[mFlatResourcesSize], kInvalidPointer, - (newSize - mFlatResourcesSize) * kElementSize); - memcpy(mFlatResources, oldResources, mFlatResourcesSize * kElementSize); + (newSize - mFlatResourcesSize) * sizeof(mFlatResources[0])); + memcpy(mFlatResources, oldResources, mFlatResourcesSize * sizeof(mFlatResources[0])); mFlatResourcesSize = newSize; delete[] oldResources; } @@ -214,6 +339,7 @@ void ResourceMap<ResourceType, IDType>::assign(IDType id, ResourceType *resource } else { + std::lock_guard<Mutex> lock(mMutex); mHashedResources[handle] = resource; } } @@ -254,7 +380,8 @@ bool UnsafeResourceMapIter<ResourceType, IDType>::empty() const template <typename ResourceType, typename IDType> void ResourceMap<ResourceType, IDType>::clear() { - memset(mFlatResources, kInvalidPointer, kInitialFlatResourcesSize * kElementSize); + // No need for a lock as this is only called on destruction. + memset(mFlatResources, kInvalidPointer, kInitialFlatResourcesSize * sizeof(mFlatResources[0])); mFlatResourcesSize = kInitialFlatResourcesSize; mHashedResources.clear(); } @@ -262,6 +389,8 @@ void ResourceMap<ResourceType, IDType>::clear() template <typename ResourceType, typename IDType> GLuint ResourceMap<ResourceType, IDType>::nextResource(size_t flatIndex, bool skipNulls) const { + // This function is only used by the iterators, access to which is marked by + // UnsafeResourceMapIter. Locking is the responsibility of the caller. for (size_t index = flatIndex; index < mFlatResourcesSize; index++) { if ((mFlatResources[index] != nullptr || !skipNulls) && diff --git a/src/libANGLE/ResourceMap_unittest.cpp b/src/libANGLE/ResourceMap_unittest.cpp index 01d2d706ba..26411fd260 100644 --- a/src/libANGLE/ResourceMap_unittest.cpp +++ b/src/libANGLE/ResourceMap_unittest.cpp @@ -8,18 +8,37 @@ // #include <gtest/gtest.h> +#include <map> #include "libANGLE/ResourceMap.h" using namespace gl; +namespace gl +{ +template <> +inline GLuint GetIDValue(int id) +{ + return id; +} +template <> +inline GLuint GetIDValue(unsigned int id) +{ + return id; +} +} // namespace gl + namespace { -// Tests assigning slots in the map and then deleting elements. -TEST(ResourceMapTest, AssignAndErase) +// The resourceMap class uses a lock for "unsigned int" types to support this unit test. +using LocklessType = int; +using LockedType = unsigned int; + +template <typename T> +void AssignAndErase() { - constexpr size_t kSize = 64; - ResourceMap<size_t, GLuint> resourceMap; + constexpr size_t kSize = 300; + ResourceMap<size_t, T> resourceMap; std::vector<size_t> objects(kSize, 1); for (size_t index = 0; index < kSize; ++index) { @@ -36,11 +55,22 @@ TEST(ResourceMapTest, AssignAndErase) ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty()); } -// Tests assigning slots in the map and then using clear() to free it. -TEST(ResourceMapTest, AssignAndClear) +// Tests assigning slots in the map and then deleting elements. +TEST(ResourceMapTest, AssignAndEraseLockless) { - constexpr size_t kSize = 64; - ResourceMap<size_t, GLuint> resourceMap; + AssignAndErase<LocklessType>(); +} +// Tests assigning slots in the map and then deleting elements. +TEST(ResourceMapTest, AssignAndEraseLocked) +{ + AssignAndErase<LockedType>(); +} + +template <typename T> +void AssignAndClear() +{ + constexpr size_t kSize = 280; + ResourceMap<size_t, T> resourceMap; std::vector<size_t> objects(kSize, 1); for (size_t index = 0; index < kSize; ++index) { @@ -51,12 +81,23 @@ TEST(ResourceMapTest, AssignAndClear) ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty()); } -// Tests growing a map more than double the size. -TEST(ResourceMapTest, BigGrowth) +// Tests assigning slots in the map and then using clear() to free it. +TEST(ResourceMapTest, AssignAndClearLockless) +{ + AssignAndClear<LocklessType>(); +} +// Tests assigning slots in the map and then using clear() to free it. +TEST(ResourceMapTest, AssignAndClearLocked) +{ + AssignAndClear<LockedType>(); +} + +template <typename T> +void BigGrowth() { constexpr size_t kSize = 8; - ResourceMap<size_t, GLuint> resourceMap; + ResourceMap<size_t, T> resourceMap; std::vector<size_t> objects; for (size_t index = 0; index < kSize; ++index) @@ -83,12 +124,26 @@ TEST(ResourceMapTest, BigGrowth) ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty()); } -// Tests querying unassigned or erased values. -TEST(ResourceMapTest, QueryUnassigned) +// Tests growing a map more than double the size. +TEST(ResourceMapTest, BigGrowthLockless) { - constexpr size_t kSize = 8; + BigGrowth<LocklessType>(); +} +// Tests growing a map more than double the size. +TEST(ResourceMapTest, BigGrowthLocked) +{ + BigGrowth<LockedType>(); +} + +template <typename T> +void QueryUnassigned() +{ + constexpr size_t kSize = 8; + constexpr T kZero = 0; + constexpr T kIdInFlatRange = 10; + constexpr T kIdOutOfFlatRange = 500; - ResourceMap<size_t, GLuint> resourceMap; + ResourceMap<size_t, T> resourceMap; std::vector<size_t> objects; for (size_t index = 0; index < kSize; ++index) @@ -96,10 +151,10 @@ TEST(ResourceMapTest, QueryUnassigned) objects.push_back(index); } - ASSERT_FALSE(resourceMap.contains(0)); - ASSERT_EQ(nullptr, resourceMap.query(0)); - ASSERT_FALSE(resourceMap.contains(100)); - ASSERT_EQ(nullptr, resourceMap.query(100)); + ASSERT_FALSE(resourceMap.contains(kZero)); + ASSERT_EQ(nullptr, resourceMap.query(kZero)); + ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange)); + ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange)); for (size_t &object : objects) { @@ -114,10 +169,10 @@ TEST(ResourceMapTest, QueryUnassigned) ASSERT_EQ(&object, resourceMap.query(object)); } - ASSERT_FALSE(resourceMap.contains(10)); - ASSERT_EQ(nullptr, resourceMap.query(10)); - ASSERT_FALSE(resourceMap.contains(100)); - ASSERT_EQ(nullptr, resourceMap.query(100)); + ASSERT_FALSE(resourceMap.contains(kIdInFlatRange)); + ASSERT_EQ(nullptr, resourceMap.query(kIdInFlatRange)); + ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange)); + ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange)); for (size_t object : objects) { @@ -128,9 +183,131 @@ TEST(ResourceMapTest, QueryUnassigned) ASSERT_TRUE(UnsafeResourceMapIter(resourceMap).empty()); - ASSERT_FALSE(resourceMap.contains(0)); - ASSERT_EQ(nullptr, resourceMap.query(0)); - ASSERT_FALSE(resourceMap.contains(100)); - ASSERT_EQ(nullptr, resourceMap.query(100)); + ASSERT_FALSE(resourceMap.contains(kZero)); + ASSERT_EQ(nullptr, resourceMap.query(kZero)); + ASSERT_FALSE(resourceMap.contains(kIdOutOfFlatRange)); + ASSERT_EQ(nullptr, resourceMap.query(kIdOutOfFlatRange)); +} + +// Tests querying unassigned or erased values. +TEST(ResourceMapTest, QueryUnassignedLockless) +{ + QueryUnassigned<LocklessType>(); +} +// Tests querying unassigned or erased values. +TEST(ResourceMapTest, QueryUnassignedLocked) +{ + QueryUnassigned<LockedType>(); +} + +void ConcurrentAccess(size_t iterations, size_t idCycleSize) +{ + if (std::is_same_v<ResourceMapMutex, angle::NoOpMutex>) + { + GTEST_SKIP() << "Test skipped: Locking is disabled in build."; + } + + constexpr size_t kThreadCount = 13; + + ResourceMap<size_t, LockedType> resourceMap; + + std::array<std::thread, kThreadCount> threads; + std::array<std::map<LockedType, size_t>, kThreadCount> insertedIds; + + for (size_t i = 0; i < kThreadCount; ++i) + { + threads[i] = std::thread([&, i]() { + // Each thread manipulates a different set of ids. The resource map guarantees that the + // data structure itself is thread-safe, not accesses to the same id. + for (size_t j = 0; j < iterations; ++j) + { + const LockedType id = (j % (idCycleSize / kThreadCount)) * kThreadCount + i; + + ASSERT_LE(id, 0xFFFFu); + ASSERT_LE(j, 0xFFFFu); + const size_t value = id | j << 16; + + size_t *valuePtr = reinterpret_cast<size_t *>(value); + + const size_t *queryResult = resourceMap.query(id); + const bool containsResult = resourceMap.contains(id); + + const bool expectContains = insertedIds[i].count(id) > 0; + if (expectContains) + { + EXPECT_TRUE(containsResult); + const LockedType queryResultInt = + static_cast<LockedType>(reinterpret_cast<size_t>(queryResult) & 0xFFFF); + const size_t queryResultIteration = reinterpret_cast<size_t>(queryResult) >> 16; + EXPECT_EQ(queryResultInt, id); + EXPECT_LT(queryResultIteration, j); + + size_t *erasedValue = nullptr; + const bool erased = resourceMap.erase(id, &erasedValue); + + EXPECT_TRUE(erased); + EXPECT_EQ(erasedValue, queryResult); + + insertedIds[i].erase(id); + } + else + { + EXPECT_FALSE(containsResult); + EXPECT_EQ(queryResult, nullptr); + + resourceMap.assign(id, valuePtr); + EXPECT_TRUE(resourceMap.contains(id)); + + ASSERT_TRUE(insertedIds[i].count(id) == 0); + insertedIds[i][id] = value; + } + } + }); + } + + for (size_t i = 0; i < kThreadCount; ++i) + { + threads[i].join(); + } + + // Verify that every value that is expected to be there is actually there + std::map<size_t, size_t> allIds; + size_t allIdsPrevSize = 0; + + for (size_t i = 0; i < kThreadCount; ++i) + { + // Merge all the sets together. The sets are disjoint, which is verified by the ASSERT_EQ. + allIds.insert(insertedIds[i].begin(), insertedIds[i].end()); + ASSERT_EQ(allIds.size(), allIdsPrevSize + insertedIds[i].size()); + allIdsPrevSize = allIds.size(); + + // Make sure every id that is expected to be there is actually there. + for (auto &idValue : insertedIds[i]) + { + EXPECT_TRUE(resourceMap.contains(idValue.first)); + EXPECT_EQ(resourceMap.query(idValue.first), reinterpret_cast<size_t *>(idValue.second)); + } + } + + // Verify that every value that is NOT expected to be there isn't actually there + for (auto &idValue : UnsafeResourceMapIter(resourceMap)) + { + EXPECT_TRUE(allIds.count(idValue.first) == 1); + EXPECT_EQ(idValue.second, reinterpret_cast<size_t *>(allIds[idValue.first])); + } + + resourceMap.clear(); +} + +// Tests that concurrent access to thread-safe resource maps works for small ids that are mostly in +// the flat map range. +TEST(ResourceMapTest, ConcurrentAccessSmallIds) +{ + ConcurrentAccess(50'000, 128); +} +// Tests that concurrent access to thread-safe resource maps works for a wider range of ids. +TEST(ResourceMapTest, ConcurrentAccessLargeIds) +{ + ConcurrentAccess(10'000, 20'000); } } // anonymous namespace diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp index 24169c0663..1f3de17a0d 100644 --- a/src/libANGLE/State.cpp +++ b/src/libANGLE/State.cpp @@ -3966,4 +3966,6 @@ void State::initializeForCapture(const Context *context) initialize(mutableContext); } +constexpr State::DirtyObjectHandler State::kDirtyObjectHandlers[state::DIRTY_OBJECT_MAX]; + } // namespace gl diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h index fa61701b30..b2aa674906 100644 --- a/src/libANGLE/State.h +++ b/src/libANGLE/State.h @@ -1448,40 +1448,13 @@ class State : angle::NonCopyable using DirtyObjectHandler = angle::Result (State::*)(const Context *context, Command command); - static constexpr std::array<DirtyObjectHandler, state::DIRTY_OBJECT_MAX> kDirtyObjectHandlers = - []() { - // Work around C++'s lack of array element support in designated initializers - std::array<DirtyObjectHandler, state::DIRTY_OBJECT_MAX> handlers{}; - - handlers[state::DIRTY_OBJECT_ACTIVE_TEXTURES] = &State::syncActiveTextures; - handlers[state::DIRTY_OBJECT_TEXTURES_INIT] = &State::syncTexturesInit; - handlers[state::DIRTY_OBJECT_IMAGES_INIT] = &State::syncImagesInit; - handlers[state::DIRTY_OBJECT_READ_ATTACHMENTS] = &State::syncReadAttachments; - handlers[state::DIRTY_OBJECT_DRAW_ATTACHMENTS] = &State::syncDrawAttachments; - handlers[state::DIRTY_OBJECT_READ_FRAMEBUFFER] = &State::syncReadFramebuffer; - handlers[state::DIRTY_OBJECT_DRAW_FRAMEBUFFER] = &State::syncDrawFramebuffer; - handlers[state::DIRTY_OBJECT_VERTEX_ARRAY] = &State::syncVertexArray; - handlers[state::DIRTY_OBJECT_TEXTURES] = &State::syncTextures; - handlers[state::DIRTY_OBJECT_IMAGES] = &State::syncImages; - handlers[state::DIRTY_OBJECT_SAMPLERS] = &State::syncSamplers; - handlers[state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT] = - &State::syncProgramPipelineObject; - - return handlers; - }(); - - static_assert( - []() { - for (auto handler : kDirtyObjectHandlers) - { - if (handler == nullptr) - { - return false; - } - } - return true; - }(), - "kDirtyObjectHandlers missing a handler"); + static constexpr DirtyObjectHandler kDirtyObjectHandlers[state::DIRTY_OBJECT_MAX] = { + &State::syncActiveTextures, &State::syncTexturesInit, + &State::syncImagesInit, &State::syncReadAttachments, + &State::syncDrawAttachments, &State::syncReadFramebuffer, + &State::syncDrawFramebuffer, &State::syncVertexArray, + &State::syncTextures, &State::syncImages, + &State::syncSamplers, &State::syncProgramPipelineObject}; // Robust init must happen before Framebuffer init for the Vulkan back-end. static_assert(state::DIRTY_OBJECT_ACTIVE_TEXTURES < state::DIRTY_OBJECT_TEXTURES_INIT, @@ -1495,6 +1468,25 @@ class State : angle::NonCopyable static_assert(state::DIRTY_OBJECT_READ_ATTACHMENTS < state::DIRTY_OBJECT_READ_FRAMEBUFFER, "init order"); + static_assert(state::DIRTY_OBJECT_ACTIVE_TEXTURES == 0, + "check DIRTY_OBJECT_ACTIVE_TEXTURES index"); + static_assert(state::DIRTY_OBJECT_TEXTURES_INIT == 1, "check DIRTY_OBJECT_TEXTURES_INIT index"); + static_assert(state::DIRTY_OBJECT_IMAGES_INIT == 2, "check DIRTY_OBJECT_IMAGES_INIT index"); + static_assert(state::DIRTY_OBJECT_READ_ATTACHMENTS == 3, + "check DIRTY_OBJECT_READ_ATTACHMENTS index"); + static_assert(state::DIRTY_OBJECT_DRAW_ATTACHMENTS == 4, + "check DIRTY_OBJECT_DRAW_ATTACHMENTS index"); + static_assert(state::DIRTY_OBJECT_READ_FRAMEBUFFER == 5, + "check DIRTY_OBJECT_READ_FRAMEBUFFER index"); + static_assert(state::DIRTY_OBJECT_DRAW_FRAMEBUFFER == 6, + "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index"); + static_assert(state::DIRTY_OBJECT_VERTEX_ARRAY == 7, "check DIRTY_OBJECT_VERTEX_ARRAY index"); + static_assert(state::DIRTY_OBJECT_TEXTURES == 8, "check DIRTY_OBJECT_TEXTURES index"); + static_assert(state::DIRTY_OBJECT_IMAGES == 9, "check DIRTY_OBJECT_IMAGES index"); + static_assert(state::DIRTY_OBJECT_SAMPLERS == 10, "check DIRTY_OBJECT_SAMPLERS index"); + static_assert(state::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT == 11, + "check DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT index"); + // Dispatch table for buffer update functions. static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters; diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp index fa27583f72..00647cbaac 100644 --- a/src/libANGLE/Texture.cpp +++ b/src/libANGLE/Texture.cpp @@ -185,8 +185,8 @@ GLuint TextureState::getMipmapMaxLevel() const GLuint expectedMipLevels = 0; if (mType == TextureType::_3D) { - const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), - baseImageDesc.size.depth); + const int maxDim = std::max( + {baseImageDesc.size.width, baseImageDesc.size.height, baseImageDesc.size.depth}); expectedMipLevels = static_cast<GLuint>(log2(maxDim)); } else @@ -594,7 +594,7 @@ GLuint TextureState::getEnabledLevelCount() const { GLuint levelCount = 0; const GLuint baseLevel = getEffectiveBaseLevel(); - const GLuint maxLevel = std::min(getEffectiveMaxLevel(), getMipmapMaxLevel()); + const GLuint maxLevel = getMipmapMaxLevel(); // The mip chain will have either one or more sequential levels, or max levels, // but not a sparse one. diff --git a/src/libANGLE/renderer/DeviceImpl.h b/src/libANGLE/renderer/DeviceImpl.h index 53d0edf72b..02eaff0ee7 100644 --- a/src/libANGLE/renderer/DeviceImpl.h +++ b/src/libANGLE/renderer/DeviceImpl.h @@ -33,7 +33,6 @@ class DeviceImpl : angle::NonCopyable virtual egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) = 0; - virtual EGLint getType() = 0; virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0; virtual const std::string getDeviceString(EGLint name); }; diff --git a/src/libANGLE/renderer/DisplayImpl.cpp b/src/libANGLE/renderer/DisplayImpl.cpp index e3258cb4be..cb12c501bc 100644 --- a/src/libANGLE/renderer/DisplayImpl.cpp +++ b/src/libANGLE/renderer/DisplayImpl.cpp @@ -27,11 +27,6 @@ class MockDevice : public DeviceImpl UNREACHABLE(); return egl::EglBadAttribute(); } - EGLint getType() override - { - UNREACHABLE(); - return EGL_NONE; - } void generateExtensions(egl::DeviceExtensions *outExtensions) const override { *outExtensions = egl::DeviceExtensions(); diff --git a/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/src/libANGLE/renderer/d3d/DeviceD3D.cpp deleted file mode 100644 index 79dfb094e3..0000000000 --- a/src/libANGLE/renderer/d3d/DeviceD3D.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright 2015 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// DeviceD3D.cpp: D3D implementation of egl::Device - -#include "libANGLE/renderer/d3d/DeviceD3D.h" - -#include "libANGLE/Device.h" -#include "libANGLE/Display.h" - -#include <EGL/eglext.h> - -namespace rx -{ - -DeviceD3D::DeviceD3D(GLint deviceType, void *nativeDevice) - : mDevice(nativeDevice), mDeviceType(deviceType), mIsInitialized(false) -{} - -DeviceD3D::~DeviceD3D() -{ -#if defined(ANGLE_ENABLE_D3D11) - if (mIsInitialized && mDeviceType == EGL_D3D11_DEVICE_ANGLE) - { - // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it. - ID3D11Device *device = static_cast<ID3D11Device *>(mDevice); - device->Release(); - } -#endif -} - -egl::Error DeviceD3D::getAttribute(const egl::Display *display, EGLint attribute, void **outValue) -{ - ASSERT(mIsInitialized); - ANGLE_UNUSED_VARIABLE(display); - // Validated at higher levels. - ASSERT(getType() == attribute); - *outValue = mDevice; - return egl::NoError(); -} - -egl::Error DeviceD3D::initialize() -{ - ASSERT(!mIsInitialized); - -#if defined(ANGLE_ENABLE_D3D11) - if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) - { - // Validate the device - IUnknown *iunknown = static_cast<IUnknown *>(mDevice); - - ID3D11Device *d3dDevice = nullptr; - HRESULT hr = - iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice)); - if (FAILED(hr)) - { - return egl::EglBadAttribute() << "Invalid D3D device passed into EGLDeviceEXT"; - } - - // The QI to ID3D11Device adds a ref to the D3D11 device. - // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the - // D3D11 device. - } -#endif - - mIsInitialized = true; - - return egl::NoError(); -} - -EGLint DeviceD3D::getType() -{ - return mDeviceType; -} - -void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const -{ - outExtensions->deviceD3D = true; -} - -} // namespace rx diff --git a/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/libANGLE/renderer/d3d/DisplayD3D.cpp index 1a2c729631..dad28b9b96 100644 --- a/src/libANGLE/renderer/d3d/DisplayD3D.cpp +++ b/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -16,7 +16,6 @@ #include "libANGLE/Surface.h" #include "libANGLE/Thread.h" #include "libANGLE/histogram_macros.h" -#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/EGLImageD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h" @@ -113,7 +112,7 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) { #if defined(ANGLE_ENABLE_D3D11) - if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE) + if (display->getDevice()->getExtensions().deviceD3D11) { rendererCreationFunctions.push_back(CreateRenderer11); } diff --git a/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/libANGLE/renderer/d3d/RendererD3D.cpp index d5b77d2003..49cbbba06d 100644 --- a/src/libANGLE/renderer/d3d/RendererD3D.cpp +++ b/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -23,7 +23,6 @@ #include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/TextureImpl.h" #include "libANGLE/renderer/d3d/BufferD3D.h" -#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h" diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h index 19e8afdc94..11e9e599ac 100644 --- a/src/libANGLE/renderer/d3d/RendererD3D.h +++ b/src/libANGLE/renderer/d3d/RendererD3D.h @@ -45,7 +45,6 @@ namespace rx class ContextImpl; struct D3DUniform; struct D3DVarying; -class DeviceD3D; class EGLImageD3D; class FramebufferImpl; class ImageD3D; diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp index 141cbe6a82..8d3313e1d3 100644 --- a/src/libANGLE/renderer/d3d/TextureD3D.cpp +++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -413,7 +413,7 @@ GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) c mRenderer->getNativeExtensions().textureNpotOES) { // Maximum number of levels - return gl::log2(std::max(std::max(width, height), depth)) + 1; + return gl::log2(std::max({width, height, depth})) + 1; } else { diff --git a/src/libANGLE/renderer/d3d/d3d11/Device11.cpp b/src/libANGLE/renderer/d3d/d3d11/Device11.cpp new file mode 100644 index 0000000000..350fa3ce89 --- /dev/null +++ b/src/libANGLE/renderer/d3d/d3d11/Device11.cpp @@ -0,0 +1,63 @@ +// +// Copyright 2024 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Device11.cpp: D3D11 implementation of egl::Device + +#include "libANGLE/renderer/d3d/d3d11/Device11.h" + +#include "libANGLE/Device.h" +#include "libANGLE/Display.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +Device11::Device11(void *nativeDevice) +{ + // Validate the device + IUnknown *iunknown = static_cast<IUnknown *>(nativeDevice); + + // The QI to ID3D11Device adds a ref to the D3D11 device. + // Deliberately don't release the ref here, so that the Device11 holds a ref to the + // D3D11 device. + iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&mDevice)); +} + +Device11::~Device11() +{ + if (mDevice) + { + // Device11 holds a ref to an externally-sourced D3D11 device. We must release it. + mDevice->Release(); + mDevice = nullptr; + } +} + +egl::Error Device11::getAttribute(const egl::Display *display, EGLint attribute, void **outValue) +{ + ASSERT(attribute == EGL_D3D11_DEVICE_ANGLE); + *outValue = mDevice; + return egl::NoError(); +} + +egl::Error Device11::initialize() +{ + if (!mDevice) + { + return egl::EglBadAttribute() << "Invalid D3D device passed into EGLDeviceEXT"; + } + + return egl::NoError(); +} + +void Device11::generateExtensions(egl::DeviceExtensions *outExtensions) const +{ + outExtensions->deviceD3D = true; + outExtensions->deviceD3D11 = true; +} + +} // namespace rx diff --git a/src/libANGLE/renderer/d3d/DeviceD3D.h b/src/libANGLE/renderer/d3d/d3d11/Device11.h index c169eb7de5..81690a4d67 100644 --- a/src/libANGLE/renderer/d3d/DeviceD3D.h +++ b/src/libANGLE/renderer/d3d/d3d11/Device11.h @@ -1,39 +1,38 @@ // -// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Copyright 2024 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// DeviceD3D.h: D3D implementation of egl::Device +// Device11.h: D3D11 implementation of egl::Device -#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_ -#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_ +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEVICE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DEVICE11_H_ #include "libANGLE/Device.h" #include "libANGLE/renderer/DeviceImpl.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { -class DeviceD3D : public DeviceImpl +class Device11 : public DeviceImpl { public: - DeviceD3D(EGLint deviceType, void *nativeDevice); - ~DeviceD3D() override; + Device11(void *nativeDevice); + ~Device11() override; egl::Error initialize() override; egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; + ID3D11Device* getDevice() const { return mDevice; } + private: - void *mDevice; - EGLint mDeviceType; - bool mIsInitialized; + ID3D11Device *mDevice = nullptr; }; } // namespace rx -#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_DEVICE11_H_ diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 6d9cfe1092..fe015f6c69 100644 --- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -27,7 +27,6 @@ #include "libANGLE/formatutils.h" #include "libANGLE/histogram_macros.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" @@ -40,6 +39,7 @@ #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Clear11.h" #include "libANGLE/renderer/d3d/d3d11/Context11.h" +#include "libANGLE/renderer/d3d/d3d11/Device11.h" #include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h" #include "libANGLE/renderer/d3d/d3d11/Fence11.h" #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" @@ -701,14 +701,10 @@ egl::Error Renderer11::initializeDXGIAdapter() { ASSERT(mRequestedDriverType == D3D_DRIVER_TYPE_UNKNOWN); - DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice()); - ASSERT(deviceD3D != nullptr); + Device11 *device11 = GetImplAs<Device11>(mDisplay->getDevice()); + ASSERT(device11 != nullptr); - // We should use the inputted D3D11 device instead - void *device = nullptr; - ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device)); - - ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device); + ID3D11Device *d3dDevice = device11->getDevice(); if (FAILED(d3dDevice->GetDeviceRemovedReason())) { return egl::EglNotInitialized() << "Inputted D3D11 device has been lost."; @@ -4227,7 +4223,7 @@ void Renderer11::initializeFrontendFeatures(angle::FrontendFeatures *features) c DeviceImpl *Renderer11::createEGLDevice() { - return new DeviceD3D(EGL_D3D11_DEVICE_ANGLE, mDevice.Get()); + return new Device11(mDevice.Get()); } ContextImpl *Renderer11::createContext(const gl::State &state, gl::ErrorSet *errorSet) diff --git a/src/libANGLE/renderer/d3d/d3d9/Device9.cpp b/src/libANGLE/renderer/d3d/d3d9/Device9.cpp new file mode 100644 index 0000000000..15a10f446d --- /dev/null +++ b/src/libANGLE/renderer/d3d/d3d9/Device9.cpp @@ -0,0 +1,41 @@ +// +// Copyright 2024 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Device9.cpp: D3D9 implementation of egl::Device + +#include "libANGLE/renderer/d3d/d3d9/Device9.h" + +#include "libANGLE/Device.h" +#include "libANGLE/Display.h" + +#include <EGL/eglext.h> + +namespace rx +{ + +Device9::Device9(IDirect3DDevice9 *device) : mDevice(device) {} + +Device9::~Device9() {} + +egl::Error Device9::getAttribute(const egl::Display *display, EGLint attribute, void **outValue) +{ + ASSERT(attribute == EGL_D3D9_DEVICE_ANGLE); + *outValue = mDevice; + return egl::NoError(); +} + +egl::Error Device9::initialize() +{ + return egl::NoError(); +} + +void Device9::generateExtensions(egl::DeviceExtensions *outExtensions) const +{ + outExtensions->deviceD3D = true; + outExtensions->deviceD3D9 = true; +} + +} // namespace rx diff --git a/src/libANGLE/renderer/d3d/d3d9/Device9.h b/src/libANGLE/renderer/d3d/d3d9/Device9.h new file mode 100644 index 0000000000..8d4db450ec --- /dev/null +++ b/src/libANGLE/renderer/d3d/d3d9/Device9.h @@ -0,0 +1,36 @@ +// +// Copyright 2024 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Device9.h: D3D9 implementation of egl::Device + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEVICE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_DEVICE9_H_ + +#include "libANGLE/Device.h" +#include "libANGLE/renderer/DeviceImpl.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Device9 : public DeviceImpl +{ + public: + Device9(IDirect3DDevice9 *device); + ~Device9() override; + + egl::Error initialize() override; + egl::Error getAttribute(const egl::Display *display, + EGLint attribute, + void **outValue) override; + void generateExtensions(egl::DeviceExtensions *outExtensions) const override; + + private: + IDirect3DDevice9 *mDevice; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D9_DEVICE9_H_ diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index cddd8d11e5..329ae54d2a 100644 --- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -26,7 +26,6 @@ #include "libANGLE/features.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" @@ -39,6 +38,7 @@ #include "libANGLE/renderer/d3d/d3d9/Blit9.h" #include "libANGLE/renderer/d3d/d3d9/Buffer9.h" #include "libANGLE/renderer/d3d/d3d9/Context9.h" +#include "libANGLE/renderer/d3d/d3d9/Device9.h" #include "libANGLE/renderer/d3d/d3d9/Fence9.h" #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" #include "libANGLE/renderer/d3d/d3d9/Image9.h" @@ -3121,7 +3121,7 @@ void Renderer9::initializeFrontendFeatures(angle::FrontendFeatures *features) co DeviceImpl *Renderer9::createEGLDevice() { - return new DeviceD3D(EGL_D3D9_DEVICE_ANGLE, mDevice); + return new Device9(mDevice); } Renderer9::CurSamplerState::CurSamplerState() diff --git a/src/libANGLE/renderer/d3d/d3d_backend.gni b/src/libANGLE/renderer/d3d/d3d_backend.gni index d262afa2ef..d17b266540 100644 --- a/src/libANGLE/renderer/d3d/d3d_backend.gni +++ b/src/libANGLE/renderer/d3d/d3d_backend.gni @@ -10,8 +10,6 @@ d3d_shared_sources = [ "CompilerD3D.cpp", "CompilerD3D.h", "ContextD3D.h", - "DeviceD3D.cpp", - "DeviceD3D.h", "DisplayD3D.cpp", "DisplayD3D.h", "DynamicHLSL.cpp", @@ -73,6 +71,8 @@ if (angle_enable_d3d9) { "d3d9/Context9.h", "d3d9/DebugAnnotator9.cpp", "d3d9/DebugAnnotator9.h", + "d3d9/Device9.cpp", + "d3d9/Device9.h", "d3d9/Fence9.cpp", "d3d9/Fence9.h", "d3d9/Framebuffer9.cpp", @@ -132,6 +132,8 @@ if (angle_enable_d3d11) { "d3d11/Context11.h", "d3d11/DebugAnnotator11.cpp", "d3d11/DebugAnnotator11.h", + "d3d11/Device11.cpp", + "d3d11/Device11.h", "d3d11/ExternalImageSiblingImpl11.cpp", "d3d11/ExternalImageSiblingImpl11.h", "d3d11/Fence11.cpp", diff --git a/src/libANGLE/renderer/driver_utils.cpp b/src/libANGLE/renderer/driver_utils.cpp index fed3940a00..641e5f7818 100644 --- a/src/libANGLE/renderer/driver_utils.cpp +++ b/src/libANGLE/renderer/driver_utils.cpp @@ -138,6 +138,16 @@ const uint16_t IntelGen12[] = { // DG1 0x4905, 0x4906, 0x4907, 0x4908, 0x4909}; +// The following is used to parse generic Vulkan driver versions. +angle::VersionTriple ParseGenericVulkanDriverVersion(uint32_t driverVersion) +{ + // Generic Vulkan driver versions are built using the following format: + // (Major << 22) | (Minor << 12) | (Patch) + constexpr uint32_t kMinorVersionMask = angle::BitMask<uint32_t>(10); + constexpr uint32_t kPatchVersionMask = angle::BitMask<uint32_t>(12); + return angle::VersionTriple(driverVersion >> 22, (driverVersion >> 12) & kMinorVersionMask, + driverVersion & kPatchVersionMask); +} } // anonymous namespace IntelDriverVersion::IntelDriverVersion(uint32_t buildNumber) : mBuildNumber(buildNumber) {} @@ -305,14 +315,14 @@ IntelDriverVersion ParseIntelWindowsDriverVersion(uint32_t driverVersion) #endif } -ARMDriverVersion ParseARMDriverVersion(uint32_t driverVersion) +ARMDriverVersion ParseARMVulkanDriverVersion(uint32_t driverVersion) { - // ARM driver versions are built with the following macro: - // ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch))) - constexpr uint32_t kMinorVersionMask = angle::BitMask<uint32_t>(10); - constexpr uint32_t kPatchMask = angle::BitMask<uint32_t>(12); - return ARMDriverVersion(driverVersion >> 22, (driverVersion >> 12) & kMinorVersionMask, - driverVersion & kPatchMask); + return ParseGenericVulkanDriverVersion(driverVersion); +} + +QualcommDriverVersion ParseQualcommVulkanDriverVersion(uint32_t driverVersion) +{ + return ParseGenericVulkanDriverVersion(driverVersion); } int GetAndroidSDKVersion() diff --git a/src/libANGLE/renderer/driver_utils.h b/src/libANGLE/renderer/driver_utils.h index f3247c78fb..b98f80c7c5 100644 --- a/src/libANGLE/renderer/driver_utils.h +++ b/src/libANGLE/renderer/driver_utils.h @@ -199,7 +199,10 @@ bool Is11thGenIntel(uint32_t DeviceId); bool Is12thGenIntel(uint32_t DeviceId); using ARMDriverVersion = angle::VersionTriple; -ARMDriverVersion ParseARMDriverVersion(uint32_t driverVersion); +ARMDriverVersion ParseARMVulkanDriverVersion(uint32_t driverVersion); + +using QualcommDriverVersion = angle::VersionTriple; +QualcommDriverVersion ParseQualcommVulkanDriverVersion(uint32_t driverVersion); // Platform helpers using angle::IsAndroid; diff --git a/src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp b/src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp index 3890d94f3f..dac2e77103 100644 --- a/src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp +++ b/src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp @@ -42,11 +42,6 @@ egl::Error DeviceCGL::getAttribute(const egl::Display *display, EGLint attribute return egl::NoError(); } -EGLint DeviceCGL::getType() -{ - return 0; -} - void DeviceCGL::generateExtensions(egl::DeviceExtensions *outExtensions) const { outExtensions->deviceCGL = true; diff --git a/src/libANGLE/renderer/gl/cgl/DeviceCGL.h b/src/libANGLE/renderer/gl/cgl/DeviceCGL.h index 3f7e1c0835..e62a6c3761 100644 --- a/src/libANGLE/renderer/gl/cgl/DeviceCGL.h +++ b/src/libANGLE/renderer/gl/cgl/DeviceCGL.h @@ -24,7 +24,6 @@ class DeviceCGL : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; }; diff --git a/src/libANGLE/renderer/gl/eagl/DeviceEAGL.cpp b/src/libANGLE/renderer/gl/eagl/DeviceEAGL.cpp index 9aa5094985..a7786f93da 100644 --- a/src/libANGLE/renderer/gl/eagl/DeviceEAGL.cpp +++ b/src/libANGLE/renderer/gl/eagl/DeviceEAGL.cpp @@ -40,11 +40,6 @@ egl::Error DeviceEAGL::getAttribute(const egl::Display *display, EGLint attribut return egl::NoError(); } -EGLint DeviceEAGL::getType() -{ - return 0; -} - void DeviceEAGL::generateExtensions(egl::DeviceExtensions *outExtensions) const { outExtensions->deviceEAGL = true; diff --git a/src/libANGLE/renderer/gl/eagl/DeviceEAGL.h b/src/libANGLE/renderer/gl/eagl/DeviceEAGL.h index 1b4a2db566..f9de40fdc2 100644 --- a/src/libANGLE/renderer/gl/eagl/DeviceEAGL.h +++ b/src/libANGLE/renderer/gl/eagl/DeviceEAGL.h @@ -24,7 +24,6 @@ class DeviceEAGL : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; }; diff --git a/src/libANGLE/renderer/gl/egl/DeviceEGL.cpp b/src/libANGLE/renderer/gl/egl/DeviceEGL.cpp index f3ee4404a0..bc2c4946bd 100644 --- a/src/libANGLE/renderer/gl/egl/DeviceEGL.cpp +++ b/src/libANGLE/renderer/gl/egl/DeviceEGL.cpp @@ -46,12 +46,6 @@ egl::Error DeviceEGL::getAttribute(const egl::Display *display, EGLint attribute return egl::EglBadAttribute(); } -EGLint DeviceEGL::getType() -{ - UNREACHABLE(); - return EGL_NONE; -} - void DeviceEGL::generateExtensions(egl::DeviceExtensions *outExtensions) const { if (hasExtension("EGL_EXT_device_drm")) diff --git a/src/libANGLE/renderer/gl/egl/DeviceEGL.h b/src/libANGLE/renderer/gl/egl/DeviceEGL.h index 10a1cf68fb..6bf0b5622e 100644 --- a/src/libANGLE/renderer/gl/egl/DeviceEGL.h +++ b/src/libANGLE/renderer/gl/egl/DeviceEGL.h @@ -27,7 +27,6 @@ class DeviceEGL : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; const std::string getDeviceString(EGLint name) override; diff --git a/src/libANGLE/renderer/gl/egl/SyncEGL.cpp b/src/libANGLE/renderer/gl/egl/SyncEGL.cpp index 93e3151eaf..2ccc9fe523 100644 --- a/src/libANGLE/renderer/gl/egl/SyncEGL.cpp +++ b/src/libANGLE/renderer/gl/egl/SyncEGL.cpp @@ -28,7 +28,13 @@ void SyncEGL::onDestroy(const egl::Display *display) { egl::Display::GetCurrentThreadUnlockedTailCall()->add( [egl = mEGL, sync = mSync](void *resultOut) { - *static_cast<EGLBoolean *>(resultOut) = egl->destroySyncKHR(sync); + EGLBoolean result = egl->destroySyncKHR(sync); + if (resultOut) + { + // It's possible for resultOut to be null if this sync is being destructed as + // part of display destruction. + *static_cast<EGLBoolean *>(resultOut) = result; + } }); mSync = EGL_NO_SYNC_KHR; } diff --git a/src/libANGLE/renderer/metal/DeviceMtl.h b/src/libANGLE/renderer/metal/DeviceMtl.h index ff8bc42e86..2fc9885e4c 100644 --- a/src/libANGLE/renderer/metal/DeviceMtl.h +++ b/src/libANGLE/renderer/metal/DeviceMtl.h @@ -26,7 +26,6 @@ class DeviceMtl : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; }; diff --git a/src/libANGLE/renderer/metal/DeviceMtl.mm b/src/libANGLE/renderer/metal/DeviceMtl.mm index d29b6aefc9..9706e721fa 100644 --- a/src/libANGLE/renderer/metal/DeviceMtl.mm +++ b/src/libANGLE/renderer/metal/DeviceMtl.mm @@ -24,6 +24,7 @@ egl::Error DeviceMtl::initialize() { return egl::NoError(); } + egl::Error DeviceMtl::getAttribute(const egl::Display *display, EGLint attribute, void **outValue) { DisplayMtl *displayImpl = mtl::GetImpl(display); @@ -39,13 +40,10 @@ egl::Error DeviceMtl::getAttribute(const egl::Display *display, EGLint attribute return egl::NoError(); } -EGLint DeviceMtl::getType() -{ - return 0; -} + void DeviceMtl::generateExtensions(egl::DeviceExtensions *outExtensions) const { outExtensions->deviceMetal = true; } -} +} // namespace rx diff --git a/src/libANGLE/renderer/metal/TextureMtl.mm b/src/libANGLE/renderer/metal/TextureMtl.mm index a0bef18639..1febc2a037 100644 --- a/src/libANGLE/renderer/metal/TextureMtl.mm +++ b/src/libANGLE/renderer/metal/TextureMtl.mm @@ -1324,7 +1324,9 @@ angle::Result TextureMtl::setEGLImageTarget(const gl::Context *context, angle::Format::InternalFormatToID(image->getFormat().info->sizedInternalFormat); mFormat = contextMtl->getPixelFormat(angleFormatId); - mSlices = mNativeTexture->cubeFacesOrArrayLength(); + mSlices = mNativeTexture->cubeFacesOrArrayLength(); + mCurrentBaseLevel = 0; + mCurrentMaxLevel = mNativeTexture->mipmapLevels() - 1; ANGLE_TRY(ensureSamplerStateCreated(context)); @@ -1484,10 +1486,13 @@ angle::Result TextureMtl::bindTexImage(const gl::Context *context, egl::Surface { releaseTexture(true); - mBoundSurface = surface; - auto pBuffer = GetImplAs<OffscreenSurfaceMtl>(surface); - mNativeTexture = pBuffer->getColorTexture(); - mFormat = pBuffer->getColorFormat(); + mBoundSurface = surface; + auto pBuffer = GetImplAs<OffscreenSurfaceMtl>(surface); + mNativeTexture = pBuffer->getColorTexture(); + mFormat = pBuffer->getColorFormat(); + mSlices = mNativeTexture->cubeFacesOrArrayLength(); + mCurrentBaseLevel = 0; + mCurrentMaxLevel = mNativeTexture->mipmapLevels() - 1; ANGLE_TRY(ensureSamplerStateCreated(context)); // Tell context to rebind textures diff --git a/src/libANGLE/renderer/metal/VertexArrayMtl.mm b/src/libANGLE/renderer/metal/VertexArrayMtl.mm index b0726b984f..d3e33bf040 100644 --- a/src/libANGLE/renderer/metal/VertexArrayMtl.mm +++ b/src/libANGLE/renderer/metal/VertexArrayMtl.mm @@ -405,7 +405,9 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, const gl::VertexBinding &binding = bindings[attrib.bindingIndex]; bool attribEnabled = attrib.enabled; - if (attribEnabled && !mCurrentArrayBuffers[v] && !mCurrentArrayInlineDataPointers[v]) + if (attribEnabled && + !(mCurrentArrayBuffers[v] && mCurrentArrayBuffers[v]->getCurrentBuffer()) && + !mCurrentArrayInlineDataPointers[v]) { // Disable it to avoid crash. attribEnabled = false; @@ -476,7 +478,7 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext, cmdEncoder->setVertexBuffer(mCurrentArrayBuffers[v]->getCurrentBuffer(), bufferOffset, bufferIdx); } - else + else if (mCurrentArrayInlineDataPointers[v]) { // No buffer specified, use the client memory directly as inline constant data ASSERT(mCurrentArrayInlineDataSizes[v] <= mInlineDataMaxSize); diff --git a/src/libANGLE/renderer/metal/mtl_resources.mm b/src/libANGLE/renderer/metal/mtl_resources.mm index 7e8a0dd0b8..4fd9dec733 100644 --- a/src/libANGLE/renderer/metal/mtl_resources.mm +++ b/src/libANGLE/renderer/metal/mtl_resources.mm @@ -271,8 +271,7 @@ angle::Result Texture::Make3DTexture(ContextMtl *context, ANGLE_MTL_OBJC_SCOPE { // Use texture2DDescriptorWithPixelFormat to calculate full range mipmap range: - uint32_t maxDimen = std::max(width, height); - maxDimen = std::max(maxDimen, depth); + const uint32_t maxDimen = std::max({width, height, depth}); MTLTextureDescriptor *desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format.metalFormat width:maxDimen diff --git a/src/libANGLE/renderer/null/DeviceNULL.cpp b/src/libANGLE/renderer/null/DeviceNULL.cpp index 4f6a9a85f6..09bd4ae0ba 100644 --- a/src/libANGLE/renderer/null/DeviceNULL.cpp +++ b/src/libANGLE/renderer/null/DeviceNULL.cpp @@ -29,11 +29,6 @@ egl::Error DeviceNULL::getAttribute(const egl::Display *display, EGLint attribut return egl::EglBadAccess(); } -EGLint DeviceNULL::getType() -{ - return 0; -} - void DeviceNULL::generateExtensions(egl::DeviceExtensions *outExtensions) const {} } // namespace rx diff --git a/src/libANGLE/renderer/null/DeviceNULL.h b/src/libANGLE/renderer/null/DeviceNULL.h index a800e1501a..e43906123f 100644 --- a/src/libANGLE/renderer/null/DeviceNULL.h +++ b/src/libANGLE/renderer/null/DeviceNULL.h @@ -25,7 +25,6 @@ class DeviceNULL : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; }; diff --git a/src/libANGLE/renderer/vulkan/BUILD.gn b/src/libANGLE/renderer/vulkan/BUILD.gn index 3f60a4bd6f..eefc2ab640 100644 --- a/src/libANGLE/renderer/vulkan/BUILD.gn +++ b/src/libANGLE/renderer/vulkan/BUILD.gn @@ -119,11 +119,11 @@ template("angle_vulkan_backend_template") { if (angle_enable_cl) { deps += [ "$angle_root/third_party/clspv/:clspv_core_shared", - "$angle_root/third_party/vulkan-deps/spirv-tools/src/:spvtools", - "$angle_root/third_party/vulkan-deps/spirv-tools/src/:spvtools_opt", + "$angle_root/third_party/spirv-tools/src/:spvtools", + "$angle_root/third_party/spirv-tools/src/:spvtools_opt", ] include_dirs = [ - "$angle_root/third_party/vulkan-deps/spirv-tools/src/include", + "$angle_root/third_party/spirv-tools/src/include", "$angle_root/third_party/clspv/src/include", ] } diff --git a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp index a448fb2a48..4ee5e7819c 100644 --- a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp @@ -58,7 +58,7 @@ angle::Result CLCommandQueueVk::init() ANGLE_CL_IMPL_TRY_ERROR( vk::OutsideRenderPassCommandBuffer::InitializeCommandPool( mContext, &mCommandPool.outsideRenderPassPool, - mContext->getRenderer()->getDeviceQueueIndex(), getProtectionType()), + mContext->getRenderer()->getQueueFamilyIndex(), getProtectionType()), CL_OUT_OF_RESOURCES); ANGLE_CL_IMPL_TRY_ERROR(mContext->getRenderer()->getOutsideRenderPassCommandBufferHelper( diff --git a/src/libANGLE/renderer/vulkan/CLContextVk.cpp b/src/libANGLE/renderer/vulkan/CLContextVk.cpp index 5acd9a1a8a..0aae828100 100644 --- a/src/libANGLE/renderer/vulkan/CLContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLContextVk.cpp @@ -26,7 +26,9 @@ CLContextVk::CLContextVk(const cl::Context &context, const cl::DevicePtrs device : CLContextImpl(context), vk::Context(getPlatform()->getRenderer()), mAssociatedDevices(devicePtrs) -{} +{ + mDeviceQueueIndex = mRenderer->getDefaultDeviceQueueIndex(); +} CLContextVk::~CLContextVk() = default; diff --git a/src/libANGLE/renderer/vulkan/CommandProcessor.cpp b/src/libANGLE/renderer/vulkan/CommandProcessor.cpp index a8df7b38a8..4de90d8f28 100644 --- a/src/libANGLE/renderer/vulkan/CommandProcessor.cpp +++ b/src/libANGLE/renderer/vulkan/CommandProcessor.cpp @@ -45,6 +45,28 @@ void InitializeSubmitInfo(VkSubmitInfo *submitInfo, submitInfo->pSignalSemaphores = &signalSemaphore; } } + +void GetDeviceQueue(VkDevice device, + bool makeProtected, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue *queue) +{ + if (makeProtected) + { + VkDeviceQueueInfo2 queueInfo2 = {}; + queueInfo2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; + queueInfo2.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT; + queueInfo2.queueFamilyIndex = queueFamilyIndex; + queueInfo2.queueIndex = queueIndex; + + vkGetDeviceQueue2(device, &queueInfo2, queue); + } + else + { + vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, queue); + } +} } // namespace // SharedFence implementation @@ -1063,18 +1085,12 @@ CommandQueue::~CommandQueue() = default; void CommandQueue::destroy(Context *context) { + vk::Renderer *renderer = context->getRenderer(); + std::lock_guard<angle::SimpleMutex> lock(mMutex); std::lock_guard<angle::SimpleMutex> enqueuelock(mQueueSubmitMutex); - // Force all commands to finish by flushing all queues. - for (VkQueue queue : mQueueMap) - { - if (queue != VK_NULL_HANDLE) - { - vkQueueWaitIdle(queue); - } - } - vk::Renderer *renderer = context->getRenderer(); + mQueueMap.destroy(); // Assigns an infinite "last completed" serial to force garbage to delete. mLastCompletedSerials.fill(Serial::Infinite()); @@ -1101,7 +1117,10 @@ void CommandQueue::destroy(Context *context) ASSERT(mFinishedCommandBatches.empty()); } -angle::Result CommandQueue::init(Context *context, const DeviceQueueMap &queueMap) +angle::Result CommandQueue::init(Context *context, + const QueueFamily &queueFamily, + bool enableProtectedContent, + uint32_t queueCount) { std::lock_guard<angle::SimpleMutex> lock(mMutex); // In case Renderer gets re-initialized, we can't rely on constructor to do initialization. @@ -1109,11 +1128,10 @@ angle::Result CommandQueue::init(Context *context, const DeviceQueueMap &queueMa mLastCompletedSerials.fill(kZeroSerial); // Assign before initializing the command pools in order to get the queue family index. - mQueueMap = queueMap; - + mQueueMap.initialize(context->getDevice(), queueFamily, enableProtectedContent, 0, queueCount); ANGLE_TRY(initCommandPool(context, ProtectionType::Unprotected)); - if (queueMap.isProtected()) + if (mQueueMap.isProtected()) { ANGLE_TRY(initCommandPool(context, ProtectionType::Protected)); } @@ -1730,53 +1748,25 @@ constexpr float kVulkanQueuePriorityHigh = 1.0; const float QueueFamily::kQueuePriorities[static_cast<uint32_t>(egl::ContextPriority::EnumCount)] = {kVulkanQueuePriorityMedium, kVulkanQueuePriorityHigh, kVulkanQueuePriorityLow}; -egl::ContextPriority DeviceQueueMap::getDevicePriority(egl::ContextPriority priority) const -{ - return mPriorities[priority]; -} - DeviceQueueMap::~DeviceQueueMap() {} -DeviceQueueMap &DeviceQueueMap::operator=(const DeviceQueueMap &other) -{ - ASSERT(this != &other); - if ((this != &other) && other.valid()) - { - mIndex = other.mIndex; - mIsProtected = other.mIsProtected; - mPriorities[egl::ContextPriority::Low] = other.mPriorities[egl::ContextPriority::Low]; - mPriorities[egl::ContextPriority::Medium] = other.mPriorities[egl::ContextPriority::Medium]; - mPriorities[egl::ContextPriority::High] = other.mPriorities[egl::ContextPriority::High]; - *static_cast<angle::PackedEnumMap<egl::ContextPriority, VkQueue> *>(this) = other; - } - return *this; -} - -void QueueFamily::getDeviceQueue(VkDevice device, - bool makeProtected, - uint32_t queueIndex, - VkQueue *queue) +void DeviceQueueMap::destroy() { - if (makeProtected) - { - VkDeviceQueueInfo2 queueInfo2 = {}; - queueInfo2.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; - queueInfo2.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT; - queueInfo2.queueFamilyIndex = mIndex; - queueInfo2.queueIndex = queueIndex; - - vkGetDeviceQueue2(device, &queueInfo2, queue); - } - else + // Force all commands to finish by flushing all queues. + for (const QueueAndIndex &queueAndIndex : mQueueAndIndices) { - vkGetDeviceQueue(device, mIndex, queueIndex, queue); + if (queueAndIndex.queue != VK_NULL_HANDLE) + { + vkQueueWaitIdle(queueAndIndex.queue); + } } } -DeviceQueueMap QueueFamily::initializeQueueMap(VkDevice device, - bool makeProtected, - uint32_t queueIndex, - uint32_t queueCount) +void DeviceQueueMap::initialize(VkDevice device, + const QueueFamily &queueFamily, + bool makeProtected, + uint32_t queueIndex, + uint32_t queueCount) { // QueueIndexing: constexpr uint32_t kQueueIndexMedium = 0; @@ -1784,44 +1774,49 @@ DeviceQueueMap QueueFamily::initializeQueueMap(VkDevice device, constexpr uint32_t kQueueIndexLow = 2; ASSERT(queueCount); - ASSERT((queueIndex + queueCount) <= mProperties.queueCount); - DeviceQueueMap queueMap(mIndex, makeProtected); + ASSERT((queueIndex + queueCount) <= queueFamily.getProperties()->queueCount); + mQueueFamilyIndex = queueFamily.getQueueFamilyIndex(); + mIsProtected = makeProtected; - getDeviceQueue(device, makeProtected, queueIndex + kQueueIndexMedium, - &queueMap[egl::ContextPriority::Medium]); - queueMap.mPriorities[egl::ContextPriority::Medium] = egl::ContextPriority::Medium; + VkQueue queue = VK_NULL_HANDLE; + GetDeviceQueue(device, makeProtected, mQueueFamilyIndex, queueIndex + kQueueIndexMedium, + &queue); + mQueueAndIndices[egl::ContextPriority::Medium] = {egl::ContextPriority::Medium, queue, + queueIndex + kQueueIndexMedium}; // If at least 2 queues, High has its own queue if (queueCount > 1) { - getDeviceQueue(device, makeProtected, queueIndex + kQueueIndexHigh, - &queueMap[egl::ContextPriority::High]); - queueMap.mPriorities[egl::ContextPriority::High] = egl::ContextPriority::High; + GetDeviceQueue(device, makeProtected, mQueueFamilyIndex, queueIndex + kQueueIndexHigh, + &queue); + mQueueAndIndices[egl::ContextPriority::High] = {egl::ContextPriority::High, queue, + queueIndex + kQueueIndexHigh}; } else { - queueMap[egl::ContextPriority::High] = queueMap[egl::ContextPriority::Medium]; - queueMap.mPriorities[egl::ContextPriority::High] = egl::ContextPriority::Medium; + mQueueAndIndices[egl::ContextPriority::High] = + mQueueAndIndices[egl::ContextPriority::Medium]; } // If at least 3 queues, Low has its own queue. Adjust Low priority. if (queueCount > 2) { - getDeviceQueue(device, makeProtected, queueIndex + kQueueIndexLow, - &queueMap[egl::ContextPriority::Low]); - queueMap.mPriorities[egl::ContextPriority::Low] = egl::ContextPriority::Low; + GetDeviceQueue(device, makeProtected, mQueueFamilyIndex, queueIndex + kQueueIndexLow, + &queue); + mQueueAndIndices[egl::ContextPriority::Low] = {egl::ContextPriority::Low, queue, + queueIndex + kQueueIndexLow}; } else { - queueMap[egl::ContextPriority::Low] = queueMap[egl::ContextPriority::Medium]; - queueMap.mPriorities[egl::ContextPriority::Low] = egl::ContextPriority::Medium; + mQueueAndIndices[egl::ContextPriority::Low] = + mQueueAndIndices[egl::ContextPriority::Medium]; } - return queueMap; } -void QueueFamily::initialize(const VkQueueFamilyProperties &queueFamilyProperties, uint32_t index) +void QueueFamily::initialize(const VkQueueFamilyProperties &queueFamilyProperties, + uint32_t queueFamilyIndex) { - mProperties = queueFamilyProperties; - mIndex = index; + mProperties = queueFamilyProperties; + mQueueFamilyIndex = queueFamilyIndex; } uint32_t QueueFamily::FindIndex(const std::vector<VkQueueFamilyProperties> &queueFamilyProperties, diff --git a/src/libANGLE/renderer/vulkan/CommandProcessor.h b/src/libANGLE/renderer/vulkan/CommandProcessor.h index e4290f8cdc..92b311980a 100644 --- a/src/libANGLE/renderer/vulkan/CommandProcessor.h +++ b/src/libANGLE/renderer/vulkan/CommandProcessor.h @@ -300,12 +300,13 @@ class QueueFamily final : angle::NonCopyable static const uint32_t kQueueCount = static_cast<uint32_t>(egl::ContextPriority::EnumCount); static const float kQueuePriorities[static_cast<uint32_t>(egl::ContextPriority::EnumCount)]; - QueueFamily() : mProperties{}, mIndex(kInvalidIndex) {} + QueueFamily() : mProperties{}, mQueueFamilyIndex(kInvalidIndex) {} ~QueueFamily() {} - void initialize(const VkQueueFamilyProperties &queueFamilyProperties, uint32_t index); - bool valid() const { return (mIndex != kInvalidIndex); } - uint32_t getIndex() const { return mIndex; } + void initialize(const VkQueueFamilyProperties &queueFamilyProperties, + uint32_t queueFamilyIndex); + bool valid() const { return (mQueueFamilyIndex != kInvalidIndex); } + uint32_t getQueueFamilyIndex() const { return mQueueFamilyIndex; } const VkQueueFamilyProperties *getProperties() const { return &mProperties; } bool isGraphics() const { return ((mProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) > 0); } bool isCompute() const { return ((mProperties.queueFlags & VK_QUEUE_COMPUTE_BIT) > 0); } @@ -315,40 +316,52 @@ class QueueFamily final : angle::NonCopyable } uint32_t getDeviceQueueCount() const { return mProperties.queueCount; } - DeviceQueueMap initializeQueueMap(VkDevice device, - bool makeProtected, - uint32_t queueIndex, - uint32_t queueCount); - private: VkQueueFamilyProperties mProperties; - uint32_t mIndex; - - void getDeviceQueue(VkDevice device, bool makeProtected, uint32_t queueIndex, VkQueue *queue); + uint32_t mQueueFamilyIndex; }; -class DeviceQueueMap : public angle::PackedEnumMap<egl::ContextPriority, VkQueue> +class DeviceQueueMap final { - friend QueueFamily; - public: - DeviceQueueMap() : mIndex(QueueFamily::kInvalidIndex), mIsProtected(false) {} - DeviceQueueMap(uint32_t queueFamilyIndex, bool isProtected) - : mIndex(queueFamilyIndex), mIsProtected(isProtected) - {} - DeviceQueueMap(const DeviceQueueMap &other) = default; + DeviceQueueMap() : mQueueFamilyIndex(QueueFamily::kInvalidIndex), mIsProtected(false) {} ~DeviceQueueMap(); - DeviceQueueMap &operator=(const DeviceQueueMap &other); - bool valid() const { return (mIndex != QueueFamily::kInvalidIndex); } - uint32_t getIndex() const { return mIndex; } + void initialize(VkDevice device, + const QueueFamily &queueFamily, + bool makeProtected, + uint32_t queueIndex, + uint32_t queueCount); + void destroy(); + + bool valid() const { return (mQueueFamilyIndex != QueueFamily::kInvalidIndex); } + uint32_t getQueueFamilyIndex() const { return mQueueFamilyIndex; } bool isProtected() const { return mIsProtected; } - egl::ContextPriority getDevicePriority(egl::ContextPriority priority) const; + egl::ContextPriority getDevicePriority(egl::ContextPriority priority) const + { + return mQueueAndIndices[priority].devicePriority; + } + DeviceQueueIndex getDeviceQueueIndex(egl::ContextPriority priority) const + { + return DeviceQueueIndex(mQueueFamilyIndex, mQueueAndIndices[priority].index); + } + const VkQueue &getQueue(egl::ContextPriority priority) const + { + return mQueueAndIndices[priority].queue; + } private: - uint32_t mIndex; + uint32_t mQueueFamilyIndex; bool mIsProtected; - angle::PackedEnumMap<egl::ContextPriority, egl::ContextPriority> mPriorities; + struct QueueAndIndex + { + // The actual priority that used + egl::ContextPriority devicePriority; + VkQueue queue; + // The queueIndex used for VkGetDeviceQueue + uint32_t index; + }; + angle::PackedEnumMap<egl::ContextPriority, QueueAndIndex> mQueueAndIndices; }; // Note all public APIs of CommandQueue class must be thread safe. @@ -358,7 +371,11 @@ class CommandQueue : angle::NonCopyable CommandQueue(); ~CommandQueue(); - angle::Result init(Context *context, const DeviceQueueMap &queueMap); + angle::Result init(Context *context, + const QueueFamily &queueFamily, + bool enableProtectedContent, + uint32_t queueCount); + void destroy(Context *context); void handleDeviceLost(Renderer *renderer); @@ -369,9 +386,13 @@ class CommandQueue : angle::NonCopyable { return mQueueMap.getDevicePriority(priority); } - uint32_t getDeviceQueueIndex() const { return mQueueMap.getIndex(); } - VkQueue getQueue(egl::ContextPriority priority) const { return mQueueMap[priority]; } + DeviceQueueIndex getDeviceQueueIndex(egl::ContextPriority priority) const + { + return mQueueMap.getDeviceQueueIndex(priority); + } + + VkQueue getQueue(egl::ContextPriority priority) const { return mQueueMap.getQueue(priority); } Serial getLastSubmittedSerial(SerialIndex index) const { return mLastSubmittedSerials[index]; } @@ -513,7 +534,7 @@ class CommandQueue : angle::NonCopyable angle::Result initCommandPool(Context *context, ProtectionType protectionType) { PersistentCommandPool &commandPool = mPrimaryCommandPoolMap[protectionType]; - return commandPool.init(context, protectionType, mQueueMap.getIndex()); + return commandPool.init(context, protectionType, mQueueMap.getQueueFamilyIndex()); } // Protect multi-thread access to mInFlightCommands.pop and ensure ordering of submission. @@ -636,6 +657,8 @@ class CommandProcessor : public Context } Serial getLastEnqueuedSerial(SerialIndex index) const { return mLastEnqueuedSerials[index]; } + std::thread::id getThreadId() const { return mTaskThread.get_id(); } + private: bool hasPendingError() const { diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp index 39ca051602..05c8a3bd00 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.cpp +++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp @@ -1209,6 +1209,12 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Rendere mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING); } + // Stash the mRefCountedEventRecycler in vk::Context for ImageHelper to conveniently access + mShareGroupRefCountedEventsGarbageRecycler = + mShareGroupVk->getRefCountedEventsGarbageRecycler(); + + mDeviceQueueIndex = renderer->getDeviceQueueIndex(mContextPriority); + angle::PerfMonitorCounterGroup vulkanGroup; vulkanGroup.name = "vulkan"; @@ -1255,6 +1261,7 @@ void ContextVk::onDestroy(const gl::Context *context) VkDevice device = getDevice(); + mRenderer->getRefCountedEventRecycler()->destroy(getDevice()); mDefaultUniformStorage.release(mRenderer); mEmptyBuffer.release(mRenderer); @@ -1403,10 +1410,10 @@ angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadCont // Assign initial command buffers from queue ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool( - this, &mCommandPools.outsideRenderPassPool, mRenderer->getDeviceQueueIndex(), + this, &mCommandPools.outsideRenderPassPool, mRenderer->getQueueFamilyIndex(), getProtectionType())); ANGLE_TRY(vk::RenderPassCommandBuffer::InitializeCommandPool( - this, &mCommandPools.renderPassPool, mRenderer->getDeviceQueueIndex(), + this, &mCommandPools.renderPassPool, mRenderer->getQueueFamilyIndex(), getProtectionType())); ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper( this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommandsAllocator, @@ -3648,6 +3655,9 @@ angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore, // Now that we have submitted commands, some of pending garbage may no longer pending // and should be moved to garbage list. mRenderer->cleanupPendingSubmissionGarbage(); + // In case of big amount of render/submission within one frame, if we accumulate excessive + // amount of garbage, also trigger the cleanup. + mShareGroupVk->cleanupExcessiveRefCountedEventGarbage(mRenderer); mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits; @@ -7687,12 +7697,18 @@ angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore, // Try to detect frame boundary for both on screen and offscreen usage by detecting // fush/finish/swap. - if ((renderPassClosureReason == RenderPassClosureReason::GLFlush || - renderPassClosureReason == RenderPassClosureReason::GLFinish || - renderPassClosureReason == RenderPassClosureReason::EGLSwapBuffers) && - mShareGroupVk->isDueForBufferPoolPrune(mRenderer)) + bool frameBoundary = renderPassClosureReason == RenderPassClosureReason::GLFlush || + renderPassClosureReason == RenderPassClosureReason::GLFinish || + renderPassClosureReason == RenderPassClosureReason::EGLSwapBuffers; + if (frameBoundary) { - mShareGroupVk->pruneDefaultBufferPools(mRenderer); + if (mShareGroupVk->isDueForBufferPoolPrune(mRenderer)) + { + mShareGroupVk->pruneDefaultBufferPools(mRenderer); + } + // Always clean up grabage and destroy the excessive free list at frame boundary. + mShareGroupVk->cleanupRefCountedEventGarbage(mRenderer); + mRenderer->getRefCountedEventRecycler()->destroy(getDevice()); } // Since we just flushed, deferred flush is no longer deferred. @@ -7988,6 +8004,9 @@ angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassCl mRenderPassCommands->getAttachmentOps(), &renderPass)); flushDescriptorSetUpdates(); + // Collect RefCountedEvent garbage before submitting to renderer + mRenderPassCommands->collectRefCountedEventsGarbage( + mShareGroupVk->getRefCountedEventsGarbageRecycler()); // Save the queueSerial before calling flushRenderPassCommands, which may return a new // mRenderPassCommands @@ -8269,6 +8288,11 @@ angle::Result ContextVk::flushOutsideRenderPassCommands() flushDescriptorSetUpdates(); + // Track completion of this command buffer. + mOutsideRenderPassCommands->flushSetEvents(this); + mOutsideRenderPassCommands->collectRefCountedEventsGarbage( + mShareGroupVk->getRefCountedEventsGarbageRecycler()); + // Save the queueSerial before calling flushOutsideRPCommands, which may return a new // mOutsideRenderPassCommands ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastFlushedQueueSerial, diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h index ed473f791e..c923e2415a 100644 --- a/src/libANGLE/renderer/vulkan/ContextVk.h +++ b/src/libANGLE/renderer/vulkan/ContextVk.h @@ -381,7 +381,11 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText gl::TextureBarrierVector *textureBarriers) override; // Sets effective Context Priority. Changed by ShareGroupVk. - void setPriority(egl::ContextPriority newPriority) { mContextPriority = newPriority; } + void setPriority(egl::ContextPriority newPriority) + { + mContextPriority = newPriority; + mDeviceQueueIndex = mRenderer->getDeviceQueueIndex(mContextPriority); + } VkDevice getDevice() const; // Effective Context Priority diff --git a/src/libANGLE/renderer/vulkan/DeviceVk.cpp b/src/libANGLE/renderer/vulkan/DeviceVk.cpp index d40cae4990..2d4be5d611 100644 --- a/src/libANGLE/renderer/vulkan/DeviceVk.cpp +++ b/src/libANGLE/renderer/vulkan/DeviceVk.cpp @@ -133,11 +133,6 @@ egl::Error DeviceVk::getAttribute(const egl::Display *display, EGLint attribute, } } -EGLint DeviceVk::getType() -{ - return EGL_VULKAN_DEVICE_ANGLE; -} - void DeviceVk::generateExtensions(egl::DeviceExtensions *outExtensions) const { outExtensions->deviceVulkan = true; diff --git a/src/libANGLE/renderer/vulkan/DeviceVk.h b/src/libANGLE/renderer/vulkan/DeviceVk.h index ef1a91a478..308fc997fe 100644 --- a/src/libANGLE/renderer/vulkan/DeviceVk.h +++ b/src/libANGLE/renderer/vulkan/DeviceVk.h @@ -31,7 +31,6 @@ class DeviceVk : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; vk::Renderer *getRenderer() const { return mRenderer; } diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/libANGLE/renderer/vulkan/DisplayVk.cpp index 60817ef78e..0be7c8a4f0 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.cpp +++ b/src/libANGLE/renderer/vulkan/DisplayVk.cpp @@ -179,6 +179,8 @@ egl::Error DisplayVk::initialize(egl::Display *display) getWSIExtension(), getWSILayer(), getWindowSystem(), mState.featureOverrides); ANGLE_TRY(angle::ToEGL(result, EGL_NOT_INITIALIZED)); + mDeviceQueueIndex = mRenderer->getDeviceQueueIndex(egl::ContextPriority::Medium); + InstallDebugAnnotator(display, mRenderer); // Query and cache supported surface format and colorspace for later use. diff --git a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp index 8f8752cc37..fa53172c38 100644 --- a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp +++ b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp @@ -247,7 +247,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk, VkMemoryPropertyFlags flags = hasProtectedContent ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0; ANGLE_TRY(image->initExternalMemory(contextVk, renderer->getMemoryProperties(), externalMemoryRequirements, 1, &importMemoryInfo, - renderer->getQueueFamilyIndex(), flags)); + contextVk->getDeviceQueueIndex(), flags)); return angle::Result::Continue; } diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp index 3827912729..0f9c157bc9 100644 --- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp +++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp @@ -203,15 +203,14 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat); // Transfer the image to this queue if needed - uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex(); - if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex)) + if (mImage->isQueueFamilyChangeNeccesary(contextVk->getDeviceQueueIndex())) { vk::OutsideRenderPassCommandBuffer *commandBuffer; vk::CommandBufferAccess access; access.onExternalAcquireRelease(mImage); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); mImage->changeLayoutAndQueue(contextVk, aspect, vk::ImageLayout::ColorWrite, - rendererQueueFamilyIndex, commandBuffer); + contextVk->getDeviceQueueIndex(), commandBuffer); ANGLE_TRY(contextVk->onEGLImageQueueChange()); } diff --git a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp index a916ec1e92..6dae003151 100644 --- a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp +++ b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp @@ -71,8 +71,6 @@ angle::Result SemaphoreVk::wait(gl::Context *context, ANGLE_TRY(contextVk->syncExternalMemory()); } - uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex(); - if (!bufferBarriers.empty()) { // Perform a queue ownership transfer for each buffer. @@ -87,8 +85,8 @@ angle::Result SemaphoreVk::wait(gl::Context *context, ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); // Queue ownership transfer. - bufferHelper.acquireFromExternal(VK_QUEUE_FAMILY_EXTERNAL, rendererQueueFamilyIndex, - commandBuffer); + bufferHelper.acquireFromExternal(vk::kExternalDeviceQueueIndex, + contextVk->getDeviceQueueIndex(), commandBuffer); } } @@ -114,8 +112,8 @@ angle::Result SemaphoreVk::wait(gl::Context *context, ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels()); // Queue ownership transfer and layout transition. - image.acquireFromExternal(contextVk, VK_QUEUE_FAMILY_EXTERNAL, rendererQueueFamilyIndex, - layout, commandBuffer); + image.acquireFromExternal(contextVk, vk::kExternalDeviceQueueIndex, + contextVk->getDeviceQueueIndex(), layout, commandBuffer); } } @@ -130,8 +128,6 @@ angle::Result SemaphoreVk::signal(gl::Context *context, ContextVk *contextVk = vk::GetImpl(context); vk::Renderer *renderer = contextVk->getRenderer(); - uint32_t rendererQueueFamilyIndex = renderer->getQueueFamilyIndex(); - if (!bufferBarriers.empty()) { // Perform a queue ownership transfer for each buffer. @@ -147,8 +143,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context, ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); // Queue ownership transfer. - bufferHelper.releaseToExternal(rendererQueueFamilyIndex, VK_QUEUE_FAMILY_EXTERNAL, - commandBuffer); + bufferHelper.releaseToExternal(vk::kExternalDeviceQueueIndex, commandBuffer); } } @@ -180,8 +175,8 @@ angle::Result SemaphoreVk::signal(gl::Context *context, ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); // Queue ownership transfer and layout transition. - image.releaseToExternal(contextVk, rendererQueueFamilyIndex, VK_QUEUE_FAMILY_EXTERNAL, - layout, commandBuffer); + image.releaseToExternal(contextVk, vk::kExternalDeviceQueueIndex, layout, + commandBuffer); } } diff --git a/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp b/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp index 26a3c1c1c5..c054a8c010 100644 --- a/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp +++ b/src/libANGLE/renderer/vulkan/ShareGroupVk.cpp @@ -160,6 +160,8 @@ void ShareGroupVk::onDestroy(const egl::Display *display) DisplayVk *displayVk = vk::GetImpl(display); vk::Renderer *renderer = displayVk->getRenderer(); + mRefCountedEventsGarbageRecycler.destroy(renderer); + for (std::unique_ptr<vk::BufferPool> &pool : mDefaultBufferPools) { if (pool) diff --git a/src/libANGLE/renderer/vulkan/ShareGroupVk.h b/src/libANGLE/renderer/vulkan/ShareGroupVk.h index 43bfb42250..7768785883 100644 --- a/src/libANGLE/renderer/vulkan/ShareGroupVk.h +++ b/src/libANGLE/renderer/vulkan/ShareGroupVk.h @@ -96,6 +96,24 @@ class ShareGroupVk : public ShareGroupImpl vk::WaitableMonolithicPipelineCreationTask *taskOut); void waitForCurrentMonolithicPipelineCreationTask(); + vk::RefCountedEventsGarbageRecycler *getRefCountedEventsGarbageRecycler() + { + return &mRefCountedEventsGarbageRecycler; + } + void cleanupRefCountedEventGarbage(vk::Renderer *renderer) + { + mRefCountedEventsGarbageRecycler.cleanup(renderer); + } + void cleanupExcessiveRefCountedEventGarbage(vk::Renderer *renderer) + { + // TODO: b/336844257 needs tune. + constexpr size_t kExcessiveGarbageCountThreshold = 256; + if (mRefCountedEventsGarbageRecycler.getGarbageCount() > kExcessiveGarbageCountThreshold) + { + mRefCountedEventsGarbageRecycler.cleanup(renderer); + } + } + private: angle::Result updateContextsPriority(ContextVk *contextVk, egl::ContextPriority newPriority); @@ -141,6 +159,9 @@ class ShareGroupVk : public ShareGroupImpl // Texture update manager used to flush uploaded mutable textures. TextureUpload mTextureUpload; + + // Holds RefCountedEvent that are free and ready to reuse + vk::RefCountedEventsGarbageRecycler mRefCountedEventsGarbageRecycler; }; } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp index d27035ad9e..1615dd681c 100644 --- a/src/libANGLE/renderer/vulkan/TextureVk.cpp +++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp @@ -2797,10 +2797,7 @@ angle::Result TextureVk::flushImageStagedUpdates(ContextVk *contextVk) angle::Result TextureVk::performImageQueueTransferIfNecessary(ContextVk *contextVk) { - const vk::Renderer *renderer = contextVk->getRenderer(); - - const uint32_t rendererQueueFamilyIndex = renderer->getQueueFamilyIndex(); - if (mImage->valid() && mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex)) + if (mImage->valid() && mImage->isQueueFamilyChangeNeccesary(contextVk->getDeviceQueueIndex())) { vk::ImageLayout newLayout = vk::ImageLayout::AllGraphicsShadersWrite; if (mImage->getUsage() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) @@ -2822,7 +2819,7 @@ angle::Result TextureVk::performImageQueueTransferIfNecessary(ContextVk *context access.onExternalAcquireRelease(mImage); ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer)); mImage->changeLayoutAndQueue(contextVk, mImage->getAspectFlags(), newLayout, - rendererQueueFamilyIndex, commandBuffer); + contextVk->getDeviceQueueIndex(), commandBuffer); ANGLE_TRY(contextVk->onEGLImageQueueChange()); } diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp index 526b5a0680..05feb1fd66 100644 --- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp +++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp @@ -1064,7 +1064,7 @@ angle::spirv::Blob MakeFragShader( code.reserve(169); // Header - spirv::WriteSpirvHeader(&code, kIdCount); + spirv::WriteSpirvHeader(&code, spirv::kVersion_1_0, kIdCount); // The preamble InsertPreamble(colorAttachmentCount, unresolveDepth, unresolveStencilWithShaderExport, &code); diff --git a/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp b/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp index 508be624d1..66db1a4484 100644 --- a/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp +++ b/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp @@ -446,7 +446,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk ANGLE_TRY(mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, 1, &dedicatedAllocInfoPtr, - VK_QUEUE_FAMILY_FOREIGN_EXT, flags)); + vk::kForeignDeviceQueueIndex, flags)); if (isExternal) { diff --git a/src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py b/src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py index f8233b038e..86118a7061 100644 --- a/src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py +++ b/src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py @@ -99,7 +99,7 @@ def main(): input_file_name = 'vk_mandatory_format_support_data.json' vk_format_map_path = 'vk_format_map.json' out_file_name = 'vk_mandatory_format_support_table_autogen.cpp' - vk_xml_file = '../../../../third_party/vulkan-deps/vulkan-headers/src/registry/vk.xml' + vk_xml_file = '../../../../third_party/vulkan-headers/src/registry/vk.xml' # auto_script parameters. if len(sys.argv) > 1: diff --git a/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp b/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp index 118f37744b..d52409b011 100644 --- a/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp +++ b/src/libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.cpp @@ -570,7 +570,7 @@ angle::Result DmaBufImageSiblingVkLinux::initWithFormat(DisplayVk *displayVk, return mImage->initExternalMemory( displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, allocateInfoCount, - allocateInfo.allocateInfoPtr.data(), VK_QUEUE_FAMILY_FOREIGN_EXT, flags); + allocateInfo.allocateInfoPtr.data(), vk::kForeignDeviceQueueIndex, flags); } angle::Result DmaBufImageSiblingVkLinux::initImpl(DisplayVk *displayVk) diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp index f237bca9ed..548bf79110 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp +++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp @@ -1526,13 +1526,8 @@ void CommandBufferHelperCommon::resetImpl(Context *context) ASSERT(!mAcquireNextImageSemaphore.valid()); mCommandAllocator.resetAllocator(); - // Clean up event garbage. Note that ImageHelper object may still holding reference count to it, - // so the event itself will not gets destroyed until the last refCount goes away. - if (!mRefCountedEventCollector.empty()) - { - context->getRenderer()->collectRefCountedEventsGarbage( - mQueueSerial, std::move(mRefCountedEventCollector)); - } + ASSERT(mRefCountedEvents.mask.none()); + ASSERT(mRefCountedEventCollector.empty()); } template <class DerivedT> @@ -1745,8 +1740,12 @@ void CommandBufferHelperCommon::flushSetEventsImpl(Context *context, CommandBuff ASSERT(refCountedEvent.valid()); const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[refCountedEvent.getImageLayout()]; - commandBuffer->setEvent(refCountedEvent.getEvent().getHandle(), - GetImageLayoutDstStageMask(context, layoutData)); + VkPipelineStageFlags stageMask = GetImageLayoutDstStageMask(context, layoutData); + if (refCountedEvent.needsReset()) + { + commandBuffer->resetEvent(refCountedEvent.getEvent().getHandle(), stageMask); + } + commandBuffer->setEvent(refCountedEvent.getEvent().getHandle(), stageMask); // We no longer need event, so garbage collect it. mRefCountedEventCollector.emplace_back(std::move(refCountedEvent)); } @@ -1882,6 +1881,16 @@ void OutsideRenderPassCommandBufferHelper::trackImagesWithEvent(Context *context flushSetEventsImpl(context, &mCommandBuffer); } +void OutsideRenderPassCommandBufferHelper::collectRefCountedEventsGarbage( + RefCountedEventsGarbageRecycler *garbageRecycler) +{ + ASSERT(garbageRecycler != nullptr); + if (!mRefCountedEventCollector.empty()) + { + garbageRecycler->collectGarbage(mQueueSerial, std::move(mRefCountedEventCollector)); + } +} + angle::Result OutsideRenderPassCommandBufferHelper::flushToPrimary(Context *context, CommandsState *commandsState) { @@ -2691,6 +2700,45 @@ void RenderPassCommandBufferHelper::trackImagesWithEvent(Context *context, } } +void RenderPassCommandBufferHelper::executeSetEvents(Context *context, + PrimaryCommandBuffer *primary) +{ + // Add VkCmdSetEvent here to track the completion of this renderPass. + for (ImageLayout layout : mRefCountedEvents.mask) + { + // This must have been garbage collected. The VkEvent handle should have been copied to + // VkEvents. + ASSERT(!mRefCountedEvents.map[layout].valid()); + ASSERT(mRefCountedEvents.vkEvents[layout] != VK_NULL_HANDLE); + const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[layout]; + primary->setEvent(mRefCountedEvents.vkEvents[layout], + GetImageLayoutDstStageMask(context, layoutData)); + } + mRefCountedEvents.mask.reset(); +} + +void RenderPassCommandBufferHelper::collectRefCountedEventsGarbage( + RefCountedEventsGarbageRecycler *garbageRecycler) +{ + // For render pass the VkCmdSetEvent works differently from OutsideRenderPassCommands. + // VkCmdEndRenderPass are called in the primary command buffer, and VkCmdSetEvents has to be + // issued after VkCmdEndRenderPass. This means VkCmdSetEvent has to be delayed. Because of this, + // here we simply make a local copy of the VkEvent and then add the RefCountedEvent to the + // garbage collector. No VkCmdSetEvent call is issued here (they will be issued at + // flushToPrimary time). + for (ImageLayout layout : mRefCountedEvents.mask) + { + ASSERT(mRefCountedEvents.map[layout].valid()); + mRefCountedEvents.vkEvents[layout] = mRefCountedEvents.map[layout].getEvent().getHandle(); + mRefCountedEventCollector.emplace_back(std::move(mRefCountedEvents.map[layout])); + } + + if (!mRefCountedEventCollector.empty()) + { + garbageRecycler->collectGarbage(mQueueSerial, std::move(mRefCountedEventCollector)); + } +} + angle::Result RenderPassCommandBufferHelper::beginRenderPass( ContextVk *contextVk, RenderPassFramebuffer &&framebuffer, @@ -2954,8 +3002,8 @@ angle::Result RenderPassCommandBufferHelper::flushToPrimary(Context *context, } primary.endRenderPass(); - // Call VkCmdSetEvent to track the completion of this renderPass. - flushSetEventsImpl(context, &primary); + // Now issue VkCmdSetEvents to primary command buffer + executeSetEvents(context, &primary); // Restart the command buffer. return reset(context, &commandsState->secondaryCommands); @@ -5077,8 +5125,7 @@ void PipelineBarrierArray::addDiagnosticsString(std::ostringstream &out) const // BufferHelper implementation. BufferHelper::BufferHelper() - : mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()), - mCurrentWriteAccess(0), + : mCurrentWriteAccess(0), mCurrentReadAccess(0), mCurrentWriteStages(0), mCurrentReadStages(0), @@ -5105,7 +5152,7 @@ BufferHelper &BufferHelper::operator=(BufferHelper &&other) mSuballocation = std::move(other.mSuballocation); mBufferWithUserSize = std::move(other.mBufferWithUserSize); - mCurrentQueueFamilyIndex = other.mCurrentQueueFamilyIndex; + mCurrentDeviceQueueIndex = other.mCurrentDeviceQueueIndex; mIsReleasedToExternal = other.mIsReleasedToExternal; mCurrentWriteAccess = other.mCurrentWriteAccess; mCurrentReadAccess = other.mCurrentReadAccess; @@ -5261,7 +5308,7 @@ VkResult BufferHelper::initSuballocation(Context *context, void BufferHelper::initializeBarrierTracker(Context *context) { Renderer *renderer = context->getRenderer(); - mCurrentQueueFamilyIndex = renderer->getQueueFamilyIndex(); + mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); mIsReleasedToExternal = false; mSerial = renderer->getResourceSerialFactory().generateBufferSerial(); mCurrentWriteAccess = 0; @@ -5479,41 +5526,44 @@ angle::Result BufferHelper::invalidate(Renderer *renderer) return invalidate(renderer, 0, getSize()); } -void BufferHelper::changeQueue(uint32_t newQueueFamilyIndex, - OutsideRenderPassCommandBuffer *commandBuffer) +void BufferHelper::changeQueueFamily(uint32_t srcQueueFamilyIndex, + uint32_t dstQueueFamilyIndex, + OutsideRenderPassCommandBuffer *commandBuffer) { VkBufferMemoryBarrier bufferMemoryBarrier = {}; bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; bufferMemoryBarrier.srcAccessMask = 0; bufferMemoryBarrier.dstAccessMask = 0; - bufferMemoryBarrier.srcQueueFamilyIndex = mCurrentQueueFamilyIndex; - bufferMemoryBarrier.dstQueueFamilyIndex = newQueueFamilyIndex; + bufferMemoryBarrier.srcQueueFamilyIndex = srcQueueFamilyIndex; + bufferMemoryBarrier.dstQueueFamilyIndex = dstQueueFamilyIndex; bufferMemoryBarrier.buffer = getBuffer().getHandle(); bufferMemoryBarrier.offset = getOffset(); bufferMemoryBarrier.size = getSize(); commandBuffer->bufferBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &bufferMemoryBarrier); - - mCurrentQueueFamilyIndex = newQueueFamilyIndex; } -void BufferHelper::acquireFromExternal(uint32_t externalQueueFamilyIndex, - uint32_t rendererQueueFamilyIndex, +void BufferHelper::acquireFromExternal(DeviceQueueIndex externalQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer) { - mCurrentQueueFamilyIndex = externalQueueFamilyIndex; + changeQueueFamily(externalQueueFamilyIndex.familyIndex(), newDeviceQueueIndex.familyIndex(), + commandBuffer); + mCurrentDeviceQueueIndex = newDeviceQueueIndex; mIsReleasedToExternal = false; - changeQueue(rendererQueueFamilyIndex, commandBuffer); } -void BufferHelper::releaseToExternal(uint32_t rendererQueueFamilyIndex, - uint32_t externalQueueFamilyIndex, +void BufferHelper::releaseToExternal(DeviceQueueIndex externalQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer) { - ASSERT(mCurrentQueueFamilyIndex == rendererQueueFamilyIndex); + if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueIndex.familyIndex()) + { + changeQueueFamily(mCurrentDeviceQueueIndex.familyIndex(), externalQueueIndex.familyIndex(), + commandBuffer); + mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; + } mIsReleasedToExternal = true; - changeQueue(externalQueueFamilyIndex, commandBuffer); } bool BufferHelper::isReleasedToExternal() const @@ -5663,7 +5713,7 @@ void ImageHelper::resetCachedProperties() mSamples = 1; mImageSerial = kInvalidImageSerial; mCurrentLayout = ImageLayout::Undefined; - mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max(); + mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; mIsReleasedToExternal = false; mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; mCurrentShaderReadStageMask = 0; @@ -5976,7 +6026,7 @@ angle::Result ImageHelper::initExternal(Context *context, imageInfo.initialLayout = ConvertImageLayoutToVkImageLayout(context, initialLayout); mCurrentLayout = initialLayout; - mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max(); + mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; mIsReleasedToExternal = false; mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; mCurrentShaderReadStageMask = 0; @@ -6140,8 +6190,8 @@ void ImageHelper::releaseImage(Renderer *renderer) renderer->onMemoryDealloc(mMemoryAllocationType, mAllocationSize, mMemoryTypeIndex, mVmaAllocation.getHandle()); } - mCurrentEvent.release(renderer->getDevice()); - mLastNonShaderReadOnlyEvent.release(renderer->getDevice()); + mCurrentEvent.release(renderer); + mLastNonShaderReadOnlyEvent.release(renderer); renderer->collectGarbage(mUse, &mImage, &mDeviceMemory, &mVmaAllocation); mViewFormats.clear(); mUse.reset(); @@ -6250,9 +6300,8 @@ angle::Result ImageHelper::initializeNonZeroMemory(Context *context, // Queue a DMA copy. VkSemaphore acquireNextImageSemaphore; - barrierImpl(context, getAspectFlags(), ImageLayout::TransferDst, - renderer->getQueueFamilyIndex(), nullptr, &commandBuffer, - &acquireNextImageSemaphore); + barrierImpl(context, getAspectFlags(), ImageLayout::TransferDst, context->getDeviceQueueIndex(), + nullptr, &commandBuffer, &acquireNextImageSemaphore); // SwapChain image should not come here ASSERT(acquireNextImageSemaphore == VK_NULL_HANDLE); @@ -6379,7 +6428,7 @@ VkResult ImageHelper::initMemory(Context *context, &mAllocationSize)); } - mCurrentQueueFamilyIndex = renderer->getQueueFamilyIndex(); + mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); mIsReleasedToExternal = false; *sizeOut = mAllocationSize; @@ -6424,7 +6473,7 @@ angle::Result ImageHelper::initExternalMemory(Context *context, const VkMemoryRequirements &memoryRequirements, uint32_t extraAllocationInfoCount, const void **extraAllocationInfo, - uint32_t currentQueueFamilyIndex, + DeviceQueueIndex currentDeviceQueueIndex, VkMemoryPropertyFlags flags) { // Vulkan allows up to 4 memory planes. @@ -6455,7 +6504,7 @@ angle::Result ImageHelper::initExternalMemory(Context *context, extraAllocationInfo[memoryPlane], bindImagePlaneMemoryInfoPtr, &mImage, &mMemoryTypeIndex, &mDeviceMemory)); } - mCurrentQueueFamilyIndex = currentQueueFamilyIndex; + mCurrentDeviceQueueIndex = currentDeviceQueueIndex; mIsReleasedToExternal = false; return angle::Result::Continue; @@ -6621,8 +6670,8 @@ void ImageHelper::destroy(Renderer *renderer) mVmaAllocation.getHandle()); } - mCurrentEvent.release(device); - mLastNonShaderReadOnlyEvent.release(device); + mCurrentEvent.release(renderer); + mLastNonShaderReadOnlyEvent.release(renderer); mImage.destroy(device); mDeviceMemory.destroy(device); mVmaAllocation.destroy(renderer->getAllocator()); @@ -6658,7 +6707,7 @@ void ImageHelper::init2DWeakReference(Context *context, mUsage = usage; mSamples = std::max(samples, 1); mImageSerial = context->getRenderer()->getResourceSerialFactory().generateImageSerial(); - mCurrentQueueFamilyIndex = context->getRenderer()->getQueueFamilyIndex(); + mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); mIsReleasedToExternal = false; mCurrentLayout = ImageLayout::Undefined; mLayerCount = 1; @@ -6987,21 +7036,21 @@ bool ImageHelper::isWriteBarrierNecessary(ImageLayout newLayout, void ImageHelper::changeLayoutAndQueue(Context *context, VkImageAspectFlags aspectMask, ImageLayout newLayout, - uint32_t newQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer) { - ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex)); + ASSERT(isQueueFamilyChangeNeccesary(newDeviceQueueIndex)); VkSemaphore acquireNextImageSemaphore; // barrierImpl should detect there is queue switch and fall back to pipelineBarrier properly. - barrierImpl(context, aspectMask, newLayout, newQueueFamilyIndex, nullptr, commandBuffer, + barrierImpl(context, aspectMask, newLayout, newDeviceQueueIndex, nullptr, commandBuffer, &acquireNextImageSemaphore); // SwapChain image should not get here. ASSERT(acquireNextImageSemaphore == VK_NULL_HANDLE); } void ImageHelper::acquireFromExternal(Context *context, - uint32_t externalQueueFamilyIndex, - uint32_t rendererQueueFamilyIndex, + DeviceQueueIndex externalQueueIndex, + DeviceQueueIndex newDeviceQueueIndex, ImageLayout currentLayout, OutsideRenderPassCommandBuffer *commandBuffer) { @@ -7009,17 +7058,17 @@ void ImageHelper::acquireFromExternal(Context *context, // queue. If this is not the case, it's an application bug, so ASSERT might // eventually need to change to a warning. ASSERT(mCurrentLayout == ImageLayout::ExternalPreInitialized || - mCurrentQueueFamilyIndex == externalQueueFamilyIndex); + mCurrentDeviceQueueIndex.familyIndex() == externalQueueIndex.familyIndex()); mCurrentLayout = currentLayout; - mCurrentQueueFamilyIndex = externalQueueFamilyIndex; + mCurrentDeviceQueueIndex = externalQueueIndex; mIsReleasedToExternal = false; // Only change the layout and queue if the layout is anything by Undefined. If it is undefined, // leave it to transition out as the image is used later. if (currentLayout != ImageLayout::Undefined) { - changeLayoutAndQueue(context, getAspectFlags(), mCurrentLayout, rendererQueueFamilyIndex, + changeLayoutAndQueue(context, getAspectFlags(), mCurrentLayout, newDeviceQueueIndex, commandBuffer); } @@ -7036,8 +7085,7 @@ void ImageHelper::acquireFromExternal(Context *context, } void ImageHelper::releaseToExternal(Context *context, - uint32_t rendererQueueFamilyIndex, - uint32_t externalQueueFamilyIndex, + DeviceQueueIndex externalQueueIndex, ImageLayout desiredLayout, OutsideRenderPassCommandBuffer *commandBuffer) { @@ -7045,9 +7093,10 @@ void ImageHelper::releaseToExternal(Context *context, // A layout change is unnecessary if the image that was previously acquired was never used by // GL! - if (mCurrentQueueFamilyIndex != externalQueueFamilyIndex || mCurrentLayout != desiredLayout) + if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueIndex.familyIndex() || + mCurrentLayout != desiredLayout) { - changeLayoutAndQueue(context, getAspectFlags(), desiredLayout, externalQueueFamilyIndex, + changeLayoutAndQueue(context, getAspectFlags(), desiredLayout, externalQueueIndex, commandBuffer); } @@ -7076,6 +7125,9 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( uint32_t newQueueFamilyIndex, VkImageMemoryBarrier *imageMemoryBarrier) const { + ASSERT(mCurrentDeviceQueueIndex.familyIndex() != QueueFamily::kInvalidIndex); + ASSERT(newQueueFamilyIndex != QueueFamily::kInvalidIndex); + const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout]; @@ -7084,7 +7136,7 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( imageMemoryBarrier->dstAccessMask = transitionTo.dstAccessMask; imageMemoryBarrier->oldLayout = ConvertImageLayoutToVkImageLayout(context, mCurrentLayout); imageMemoryBarrier->newLayout = ConvertImageLayoutToVkImageLayout(context, newLayout); - imageMemoryBarrier->srcQueueFamilyIndex = mCurrentQueueFamilyIndex; + imageMemoryBarrier->srcQueueFamilyIndex = mCurrentDeviceQueueIndex.familyIndex(); imageMemoryBarrier->dstQueueFamilyIndex = newQueueFamilyIndex; imageMemoryBarrier->image = mImage.getHandle(); @@ -7101,7 +7153,7 @@ template <typename CommandBufferT> void ImageHelper::barrierImpl(Context *context, VkImageAspectFlags aspectMask, ImageLayout newLayout, - uint32_t newQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut) @@ -7117,7 +7169,7 @@ void ImageHelper::barrierImpl(Context *context, { // For now we always use pipelineBarrier for singlebuffer mode. We could use event here in // future. - mCurrentEvent.release(context->getDevice()); + mCurrentEvent.release(context); const ImageMemoryBarrierData &transition = kImageMemoryBarrierData[mCurrentLayout]; VkMemoryBarrier memoryBarrier = {}; @@ -7137,7 +7189,7 @@ void ImageHelper::barrierImpl(Context *context, const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout]; VkImageMemoryBarrier imageMemoryBarrier = {}; - initImageMemoryBarrierStruct(context, aspectMask, newLayout, newQueueFamilyIndex, + initImageMemoryBarrierStruct(context, aspectMask, newLayout, newDeviceQueueIndex.familyIndex(), &imageMemoryBarrier); VkPipelineStageFlags dstStageMask = GetImageLayoutDstStageMask(context, transitionTo); @@ -7147,7 +7199,7 @@ void ImageHelper::barrierImpl(Context *context, // element of pBufferMemoryBarriers or pImageMemoryBarriers must be equal // (VUID-vkCmdWaitEvents-srcQueueFamilyIndex-02803). BarrierType barrierType = - mCurrentEvent.valid() && mCurrentQueueFamilyIndex == newQueueFamilyIndex + mCurrentEvent.valid() && mCurrentDeviceQueueIndex == newDeviceQueueIndex ? BarrierType::Event : BarrierType::Pipeline; @@ -7174,11 +7226,11 @@ void ImageHelper::barrierImpl(Context *context, } commandBuffer->imageBarrier(srcStageMask, dstStageMask, imageMemoryBarrier); // We use pipelineBarrier here, no needs to wait for events any more. - mCurrentEvent.release(context->getDevice()); + mCurrentEvent.release(context); } mCurrentLayout = newLayout; - mCurrentQueueFamilyIndex = newQueueFamilyIndex; + mCurrentDeviceQueueIndex = newDeviceQueueIndex; resetSubresourcesWrittenSinceBarrier(); // We must release the event so that new event will be created and added. If we did not add new @@ -7192,7 +7244,7 @@ template void ImageHelper::barrierImpl<priv::CommandBuffer>( Context *context, VkImageAspectFlags aspectMask, ImageLayout newLayout, - uint32_t newQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, priv::CommandBuffer *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut); @@ -7238,7 +7290,7 @@ void ImageHelper::recordWriteBarrier(Context *context, { ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - barrierImpl(context, aspectMask, newLayout, context->getRenderer()->getQueueFamilyIndex(), + barrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -7267,7 +7319,7 @@ void ImageHelper::recordReadSubresourceBarrier(Context *context, { ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - barrierImpl(context, aspectMask, newLayout, context->getRenderer()->getQueueFamilyIndex(), + barrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -7293,7 +7345,7 @@ void ImageHelper::recordReadBarrier(Context *context, ASSERT(!mCurrentEvent.valid() || !commands->hasSetEventPendingFlush(mCurrentEvent)); VkSemaphore acquireNextImageSemaphore; - barrierImpl(context, aspectMask, newLayout, context->getRenderer()->getQueueFamilyIndex(), + barrierImpl(context, aspectMask, newLayout, context->getDeviceQueueIndex(), commands->getRefCountedEventCollector(), &commands->getCommandBuffer(), &acquireNextImageSemaphore); @@ -7322,7 +7374,13 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, ASSERT(context->getRenderer()->getFeatures().useVkEventForImageBarrier.enabled || !mCurrentEvent.valid()); - if (!mCurrentEvent.valid()) + if (mCurrentDeviceQueueIndex != context->getDeviceQueueIndex()) + { + // Fallback to pipelineBarrier if the VkQueue has changed. + barrierType = BarrierType::Pipeline; + mCurrentDeviceQueueIndex = context->getDeviceQueueIndex(); + } + else if (!mCurrentEvent.valid()) { // Fallback to pipelineBarrier if there is no event tracking image. barrierType = BarrierType::Pipeline; @@ -7368,7 +7426,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, // Release it. No need to garbage collect since we did not use the event here. ALl // previous use of event should garbage tracked already. - mCurrentEvent.release(context->getDevice()); + mCurrentEvent.release(context); } mBarrierQueueSerial = queueSerial; } @@ -7394,6 +7452,8 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, return; } + ASSERT(!mLastNonShaderReadOnlyEvent.valid() || + mLastNonShaderReadOnlyEvent.getImageLayout() == mLastNonShaderReadOnlyLayout); if (!mLastNonShaderReadOnlyEvent.valid()) { barrierType = BarrierType::Pipeline; @@ -7401,8 +7461,11 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, if (barrierType == BarrierType::Event) { - eventBarriers->addMemoryEvent(context, mLastNonShaderReadOnlyEvent, dstStageMask, - transitionTo.dstAccessMask); + // If we already inserted a barrier in the same renderPass, we has to add + // the new stage mask to the existing VkCmdWaitEvent call, otherwise VVL will + // complain. + eventBarriers->addAdditionalStageAccess(mLastNonShaderReadOnlyEvent, dstStageMask, + transitionTo.dstAccessMask); eventCollector->emplace_back(mLastNonShaderReadOnlyEvent); } else @@ -7424,21 +7487,12 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, { eventCollector->emplace_back(std::move(mCurrentEvent)); } - - const ImageMemoryBarrierData &layoutData = - kImageMemoryBarrierData[mLastNonShaderReadOnlyLayout]; - pipelineBarriers->mergeMemoryBarrier( - transitionTo.barrierIndex, GetImageLayoutSrcStageMask(context, layoutData), - dstStageMask, layoutData.srcAccessMask, transitionTo.dstAccessMask); - mBarrierQueueSerial = queueSerial; - // Accumulate new read stage. - mCurrentShaderReadStageMask |= dstStageMask; } else { VkImageMemoryBarrier imageMemoryBarrier = {}; initImageMemoryBarrierStruct(context, aspectMask, newLayout, - context->getRenderer()->getQueueFamilyIndex(), + context->getDeviceQueueIndex().familyIndex(), &imageMemoryBarrier); if (transitionFrom.layout == transitionTo.layout && @@ -7483,7 +7537,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; if (mLastNonShaderReadOnlyEvent.valid()) { - mLastNonShaderReadOnlyEvent.release(context->getDevice()); + mLastNonShaderReadOnlyEvent.release(context); } } @@ -7492,7 +7546,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, const bool isShaderReadOnly = IsShaderReadOnlyLayout(transitionTo); if (isShaderReadOnly) { - mLastNonShaderReadOnlyEvent.release(context->getDevice()); + mLastNonShaderReadOnlyEvent.release(context); mLastNonShaderReadOnlyLayout = mCurrentLayout; mCurrentShaderReadStageMask = dstStageMask; } @@ -7511,7 +7565,7 @@ void ImageHelper::updateLayoutAndBarrier(Context *context, { pipelineBarriers->mergeImageBarrier(transitionTo.barrierIndex, srcStageMask, dstStageMask, imageMemoryBarrier); - mCurrentEvent.release(context->getDevice()); + mCurrentEvent.release(context); } mBarrierQueueSerial = queueSerial; @@ -7531,17 +7585,22 @@ void ImageHelper::setCurrentRefCountedEvent(Context *context, ImageLayoutEventMa { ASSERT(context->getRenderer()->getFeatures().useVkEventForImageBarrier.enabled); + // If there is already an event, release it first. + mCurrentEvent.release(context); + // Create the event if we have not yet so. Otherwise just use the already created event. This // means all images used in the same render pass that has the same layout will be tracked by the // same event. if (!layoutEventMaps.map[mCurrentLayout].valid()) { - layoutEventMaps.map[mCurrentLayout].init(context, mCurrentLayout); + if (!layoutEventMaps.map[mCurrentLayout].init(context, mCurrentLayout)) + { + // If VkEvent creation fail, we fallback to pipelineBarrier + return; + } layoutEventMaps.mask.set(mCurrentLayout); } - // If there is already an event, release it first. - mCurrentEvent.release(context->getDevice()); // Copy the event to mCurrentEvent so that we can wait for it in future. This will add extra // refcount to the underlying VkEvent. mCurrentEvent = layoutEventMaps.map[mCurrentLayout]; @@ -9279,7 +9338,7 @@ void ImageHelper::stageSelfAsSubresourceUpdates( prevImage->get().mIntendedFormatID = mIntendedFormatID; prevImage->get().mActualFormatID = mActualFormatID; prevImage->get().mCurrentLayout = mCurrentLayout; - prevImage->get().mCurrentQueueFamilyIndex = mCurrentQueueFamilyIndex; + prevImage->get().mCurrentDeviceQueueIndex = mCurrentDeviceQueueIndex; prevImage->get().mLastNonShaderReadOnlyLayout = mLastNonShaderReadOnlyLayout; prevImage->get().mCurrentShaderReadStageMask = mCurrentShaderReadStageMask; prevImage->get().mLevelCount = levelCount; @@ -9291,7 +9350,7 @@ void ImageHelper::stageSelfAsSubresourceUpdates( // Reset information for current (invalid) image. mCurrentLayout = ImageLayout::Undefined; - mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max(); + mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex; mIsReleasedToExternal = false; mLastNonShaderReadOnlyLayout = ImageLayout::Undefined; mCurrentShaderReadStageMask = 0; @@ -10206,7 +10265,7 @@ angle::Result ImageHelper::copySurfaceImageToBuffer(DisplayVk *displayVk, // We may have a valid event here but we do not have a collector to collect it. Release the // event here to force pipelineBarrier. - mCurrentEvent.release(displayVk->getDevice()); + mCurrentEvent.release(displayVk->getRenderer()); PrimaryCommandBuffer primaryCommandBuffer; ANGLE_TRY(renderer->getCommandBufferOneOff(displayVk, ProtectionType::Unprotected, @@ -10214,7 +10273,7 @@ angle::Result ImageHelper::copySurfaceImageToBuffer(DisplayVk *displayVk, VkSemaphore acquireNextImageSemaphore; barrierImpl(displayVk, getAspectFlags(), ImageLayout::TransferSrc, - renderer->getQueueFamilyIndex(), nullptr, &primaryCommandBuffer, + displayVk->getDeviceQueueIndex(), nullptr, &primaryCommandBuffer, &acquireNextImageSemaphore); primaryCommandBuffer.copyImageToBuffer(mImage, getCurrentLayout(displayVk), bufferHelper->getBuffer().getHandle(), 1, ®ion); @@ -10258,7 +10317,7 @@ angle::Result ImageHelper::copyBufferToSurfaceImage(DisplayVk *displayVk, // We may have a valid event here but we do not have a collector to collect it. Release the // event here to force pipelineBarrier. - mCurrentEvent.release(displayVk->getDevice()); + mCurrentEvent.release(displayVk->getRenderer()); PrimaryCommandBuffer commandBuffer; ANGLE_TRY( @@ -10266,7 +10325,7 @@ angle::Result ImageHelper::copyBufferToSurfaceImage(DisplayVk *displayVk, VkSemaphore acquireNextImageSemaphore; barrierImpl(displayVk, getAspectFlags(), ImageLayout::TransferDst, - renderer->getQueueFamilyIndex(), nullptr, &commandBuffer, + displayVk->getDeviceQueueIndex(), nullptr, &commandBuffer, &acquireNextImageSemaphore); commandBuffer.copyBufferToImage(bufferHelper->getBuffer().getHandle(), mImage, getCurrentLayout(displayVk), 1, ®ion); diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h index e434f12f63..1ce7c93821 100644 --- a/src/libANGLE/renderer/vulkan/vk_helpers.h +++ b/src/libANGLE/renderer/vulkan/vk_helpers.h @@ -175,6 +175,8 @@ struct ImageLayoutEventMaps // loop of map angle::PackedEnumMap<ImageLayout, RefCountedEvent> map; angle::PackedEnumBitSet<ImageLayout, uint64_t> mask; + // Only used by RenderPassCommandBufferHelper + angle::PackedEnumMap<ImageLayout, VkEvent> vkEvents; }; // A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer, @@ -971,16 +973,17 @@ class BufferHelper : public ReadWriteResource angle::Result invalidate(Renderer *renderer); angle::Result invalidate(Renderer *renderer, VkDeviceSize offset, VkDeviceSize size); - void changeQueue(uint32_t newQueueFamilyIndex, OutsideRenderPassCommandBuffer *commandBuffer); + void changeQueueFamily(uint32_t srcQueueFamilyIndex, + uint32_t dstQueueFamilyIndex, + OutsideRenderPassCommandBuffer *commandBuffer); // Performs an ownership transfer from an external instance or API. - void acquireFromExternal(uint32_t externalQueueFamilyIndex, - uint32_t rendererQueueFamilyIndex, + void acquireFromExternal(DeviceQueueIndex externalQueueIndex, + DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer); // Performs an ownership transfer to an external instance or API. - void releaseToExternal(uint32_t rendererQueueFamilyIndex, - uint32_t externalQueueFamilyIndex, + void releaseToExternal(DeviceQueueIndex externalQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer); // Returns true if the image is owned by an external API or instance. @@ -1041,7 +1044,7 @@ class BufferHelper : public ReadWriteResource Buffer mBufferWithUserSize; // For memory barriers. - uint32_t mCurrentQueueFamilyIndex; + DeviceQueueIndex mCurrentDeviceQueueIndex; VkFlags mCurrentWriteAccess; VkFlags mCurrentReadAccess; VkPipelineStageFlags mCurrentWriteStages; @@ -1349,8 +1352,6 @@ class CommandBufferHelperCommon : angle::NonCopyable template <typename CommandBufferT> void flushSetEventsImpl(Context *context, CommandBufferT *commandBuffer); - RefCountedEventCollector *getRefCountedEventCollector() { return &mRefCountedEventCollector; } - const QueueSerial &getQueueSerial() const { return mQueueSerial; } void setAcquireNextImageSemaphore(VkSemaphore semaphore) @@ -1523,8 +1524,13 @@ class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCom void trackImagesWithEvent(Context *context, ImageHelper *srcImage, ImageHelper *dstImage); void trackImagesWithEvent(Context *context, const ImageHelperPtr *images, size_t count); - // Issues VkCmdSetEvent calls. + // Issues SetEvent calls to the command buffer. void flushSetEvents(Context *context) { flushSetEventsImpl(context, &mCommandBuffer); } + // Clean up event garbage. Note that ImageHelper object may still holding reference count to it, + // so the event itself will not gets destroyed until the last refCount goes away. + void collectRefCountedEventsGarbage(RefCountedEventsGarbageRecycler *garbageRecycler); + + RefCountedEventCollector *getRefCountedEventCollector() { return &mRefCountedEventCollector; } angle::Result flushToPrimary(Context *context, CommandsState *commandsState); @@ -1874,6 +1880,8 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon void updateDepthStencilReadOnlyMode(RenderPassUsageFlags dsUsageFlags, VkImageAspectFlags dsAspectFlags); + void collectRefCountedEventsGarbage(RefCountedEventsGarbageRecycler *garbageRecycler); + private: uint32_t getSubpassCommandBufferCount() const { return mCurrentSubpassCommandBufferIndex + 1; } @@ -1911,6 +1919,7 @@ class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon void finalizeFragmentShadingRateImageLayout(Context *context); void trackImagesWithEvent(Context *context, const ImageHelperPtr *images, size_t count); + void executeSetEvents(Context *context, PrimaryCommandBuffer *primary); // When using Vulkan secondary command buffers, each subpass must be recorded in a separate // command buffer. Currently ANGLE produces render passes with at most 2 subpasses. @@ -2092,7 +2101,7 @@ class ImageHelper final : public Resource, public angle::Subject const VkMemoryRequirements &memoryRequirements, uint32_t extraAllocationInfoCount, const void **extraAllocationInfo, - uint32_t currentQueueFamilyIndex, + DeviceQueueIndex currentDeviceQueueIndex, VkMemoryPropertyFlags flags); static constexpr VkImageUsageFlags kDefaultImageViewUsageFlags = 0; @@ -2518,7 +2527,7 @@ class ImageHelper final : public Resource, public angle::Subject // Since we are doing an out of order one off submission, there shouldn't be any pending // setEvent. ASSERT(!mCurrentEvent.valid()); - barrierImpl(context, getAspectFlags(), newLayout, mCurrentQueueFamilyIndex, nullptr, + barrierImpl(context, getAspectFlags(), newLayout, mCurrentDeviceQueueIndex, nullptr, commandBuffer, acquireNextImageSemaphoreOut); } @@ -2540,15 +2549,15 @@ class ImageHelper final : public Resource, public angle::Subject ImageLayout newLayout, OutsideRenderPassCommandBufferHelper *commands); - bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const + bool isQueueFamilyChangeNeccesary(DeviceQueueIndex newDeviceQueueIndex) const { - return mCurrentQueueFamilyIndex != newQueueFamilyIndex; + return mCurrentDeviceQueueIndex.familyIndex() != newDeviceQueueIndex.familyIndex(); } void changeLayoutAndQueue(Context *context, VkImageAspectFlags aspectMask, ImageLayout newLayout, - uint32_t newQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, OutsideRenderPassCommandBuffer *commandBuffer); // Returns true if barrier has been generated @@ -2564,15 +2573,14 @@ class ImageHelper final : public Resource, public angle::Subject // Performs an ownership transfer from an external instance or API. void acquireFromExternal(Context *context, - uint32_t externalQueueFamilyIndex, - uint32_t rendererQueueFamilyIndex, + DeviceQueueIndex externalQueueIndex, + DeviceQueueIndex newDeviceQueueIndex, ImageLayout currentLayout, OutsideRenderPassCommandBuffer *commandBuffer); // Performs an ownership transfer to an external instance or API. void releaseToExternal(Context *context, - uint32_t rendererQueueFamilyIndex, - uint32_t externalQueueFamilyIndex, + DeviceQueueIndex externalQueueIndex, ImageLayout desiredLayout, OutsideRenderPassCommandBuffer *commandBuffer); @@ -2854,7 +2862,7 @@ class ImageHelper final : public Resource, public angle::Subject void barrierImpl(Context *context, VkImageAspectFlags aspectMask, ImageLayout newLayout, - uint32_t newQueueFamilyIndex, + DeviceQueueIndex newDeviceQueueIndex, RefCountedEventCollector *eventCollector, CommandBufferT *commandBuffer, VkSemaphore *acquireNextImageSemaphoreOut); @@ -3078,7 +3086,7 @@ class ImageHelper final : public Resource, public angle::Subject // Current state. ImageLayout mCurrentLayout; - uint32_t mCurrentQueueFamilyIndex; + DeviceQueueIndex mCurrentDeviceQueueIndex; // For optimizing transition between different shader readonly layouts ImageLayout mLastNonShaderReadOnlyLayout; VkPipelineStageFlags mCurrentShaderReadStageMask; diff --git a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp index 32897a5a75..efd95edb85 100644 --- a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp +++ b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.cpp @@ -15,58 +15,189 @@ namespace rx { namespace vk { -void RefCountedEvent::init(Context *context, ImageLayout layout) +bool RefCountedEvent::init(Context *context, ImageLayout layout) { ASSERT(mHandle == nullptr); ASSERT(layout != ImageLayout::Undefined); - mHandle = new AtomicRefCounted<EventAndLayout>; - VkEventCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; - // Use device only for performance reasons. - createInfo.flags = context->getFeatures().supportsSynchronization2.enabled - ? VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR - : 0; - mHandle->get().event.init(context->getDevice(), createInfo); + // First try with recycler. We must issue VkCmdResetEvent before VkCmdSetEvent + if (context->getRefCountedEventsGarbageRecycler()->fetch(this) || + context->getRenderer()->getRefCountedEventRecycler()->fetch(this)) + { + mHandle->get().needsReset = true; + } + else + { + // If failed to fetch from recycler, then create a new event. + mHandle = new RefCounted<EventAndLayout>; + VkEventCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO; + // Use device only for performance reasons. + createInfo.flags = context->getFeatures().supportsSynchronization2.enabled + ? VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR + : 0; + VkResult result = mHandle->get().event.init(context->getDevice(), createInfo); + if (result != VK_SUCCESS) + { + WARN() << "event.init failed. Clean up garbage and retry again"; + // Proactively clean up garbage and retry + context->getRefCountedEventsGarbageRecycler()->cleanup(context->getRenderer()); + result = mHandle->get().event.init(context->getDevice(), createInfo); + if (result != VK_SUCCESS) + { + // Drivers usually can allocate huge amount of VkEvents, and we should never use + // that many VkEvents under normal situation. If we failed to allocate, there is a + // high chance that we may have a leak somewhere. This macro should help us catch + // such potential bugs in the bots if that happens. + UNREACHABLE(); + // If still fail to create, we just return. An invalid event will trigger + // pipelineBarrier code path + return false; + } + } + mHandle->get().needsReset = false; + } + mHandle->addRef(); mHandle->get().imageLayout = layout; + return true; +} + +void RefCountedEvent::release(Context *context) +{ + if (mHandle != nullptr) + { + releaseImpl(context->getRenderer(), context->getRefCountedEventsGarbageRecycler()); + } +} + +void RefCountedEvent::release(Renderer *renderer) +{ + if (mHandle != nullptr) + { + releaseImpl(renderer, renderer->getRefCountedEventRecycler()); + } +} + +template <typename RecyclerT> +void RefCountedEvent::releaseImpl(Renderer *renderer, RecyclerT *recycler) +{ + ASSERT(mHandle != nullptr); + // This should never called from async submission thread since the refcount is not atomic. It is + // expected only called under context share lock. + ASSERT(std::this_thread::get_id() != renderer->getCommandProcessorThreadId()); + + const bool isLastReference = mHandle->getAndReleaseRef() == 1; + if (isLastReference) + { + // When async submission is enabled, recycler will be null when release call comes from + // CommandProcessor. But in that case it will not be the last reference since garbage + // collector should have one reference count and will never release that reference count + // until GPU finished. + ASSERT(recycler != nullptr); + // TODO: Disable recycler and immediately destroy the event for now until I figure out + // SYNC-vkCmdSetEvent-missingbarrier-reset. + destroy(renderer->getDevice()); + ASSERT(mHandle == nullptr); + } + else + { + mHandle = nullptr; + } +} + +void RefCountedEvent::destroy(VkDevice device) +{ + ASSERT(mHandle != nullptr); + ASSERT(!mHandle->isReferenced()); + mHandle->get().event.destroy(device); + SafeDelete(mHandle); } // RefCountedEventsGarbage implementation. -bool RefCountedEventsGarbage::destroyIfComplete(Renderer *renderer) +bool RefCountedEventsGarbage::releaseIfComplete(Renderer *renderer, + RefCountedEventsGarbageRecycler *recycler) { - if (renderer->hasResourceUseFinished(mLifetime)) + if (!renderer->hasQueueSerialFinished(mQueueSerial)) { - for (RefCountedEvent &event : mRefCountedEvents) - { - ASSERT(event.valid()); - event.release(renderer->getDevice()); - ASSERT(!event.valid()); - } - mRefCountedEvents.clear(); - return true; + return false; + } + + while (!mRefCountedEvents.empty()) + { + ASSERT(mRefCountedEvents.back().valid()); + mRefCountedEvents.back().releaseImpl(renderer, recycler); + ASSERT(!mRefCountedEvents.back().valid()); + mRefCountedEvents.pop_back(); + } + return true; +} + +void RefCountedEventsGarbage::destroy(Renderer *renderer) +{ + ASSERT(renderer->hasQueueSerialFinished(mQueueSerial)); + while (!mRefCountedEvents.empty()) + { + ASSERT(mRefCountedEvents.back().valid()); + mRefCountedEvents.back().release(renderer); + mRefCountedEvents.pop_back(); } - return false; } -bool RefCountedEventsGarbage::hasResourceUseSubmitted(Renderer *renderer) const +// RefCountedEventsGarbageRecycler implementation. +RefCountedEventsGarbageRecycler::~RefCountedEventsGarbageRecycler() { - return renderer->hasResourceUseSubmitted(mLifetime); + ASSERT(mFreeStack.empty()); + ASSERT(mGarbageQueue.empty()); } -// EventBarrier implementation. -bool EventBarrier::hasEvent(const VkEvent &event) const +void RefCountedEventsGarbageRecycler::destroy(Renderer *renderer) { - for (const VkEvent &existingEvent : mEvents) + while (!mGarbageQueue.empty()) { - if (existingEvent == event) + mGarbageQueue.front().destroy(renderer); + mGarbageQueue.pop(); + } + + mFreeStack.destroy(renderer->getDevice()); +} + +void RefCountedEventsGarbageRecycler::cleanup(Renderer *renderer) +{ + // Destroy free stack first. The garbage clean up process will add more events to the free + // stack. If everything is stable between each frame, grabage should release enough events to + // recycler for next frame's needs. + mFreeStack.destroy(renderer->getDevice()); + + while (!mGarbageQueue.empty()) + { + size_t count = mGarbageQueue.front().size(); + bool released = mGarbageQueue.front().releaseIfComplete(renderer, this); + if (released) { - return true; + mGarbageCount -= count; + mGarbageQueue.pop(); } + else + { + break; + } + } +} + +bool RefCountedEventsGarbageRecycler::fetch(RefCountedEvent *outObject) +{ + if (!mFreeStack.empty()) + { + mFreeStack.fetch(outObject); + ASSERT(outObject->valid()); + ASSERT(!outObject->mHandle->isReferenced()); + return true; } return false; } +// EventBarrier implementation. void EventBarrier::addDiagnosticsString(std::ostringstream &out) const { if (mMemoryBarrierSrcAccess != 0 || mMemoryBarrierDstAccess != 0) @@ -82,50 +213,47 @@ void EventBarrier::execute(PrimaryCommandBuffer *primary) { return; } + ASSERT(mEvent != VK_NULL_HANDLE); + ASSERT(mImageMemoryBarrierCount == 0 || + (mImageMemoryBarrierCount == 1 && mImageMemoryBarrier.image != VK_NULL_HANDLE)); // Issue vkCmdWaitEvents call VkMemoryBarrier memoryBarrier = {}; - uint32_t memoryBarrierCount = 0; - if (mMemoryBarrierDstAccess != 0) - { - memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - memoryBarrier.srcAccessMask = mMemoryBarrierSrcAccess; - memoryBarrier.dstAccessMask = mMemoryBarrierDstAccess; - memoryBarrierCount++; - } + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.srcAccessMask = mMemoryBarrierSrcAccess; + memoryBarrier.dstAccessMask = mMemoryBarrierDstAccess; - primary->waitEvents(static_cast<uint32_t>(mEvents.size()), mEvents.data(), mSrcStageMask, - mDstStageMask, memoryBarrierCount, &memoryBarrier, 0, nullptr, - static_cast<uint32_t>(mImageMemoryBarriers.size()), - mImageMemoryBarriers.data()); - - reset(); + primary->waitEvents(1, &mEvent, mSrcStageMask, mDstStageMask, 1, &memoryBarrier, 0, nullptr, + mImageMemoryBarrierCount, + mImageMemoryBarrierCount == 0 ? nullptr : &mImageMemoryBarrier); } // EventBarrierArray implementation. -void EventBarrierArray::addMemoryEvent(Context *context, - const RefCountedEvent &waitEvent, - VkPipelineStageFlags dstStageMask, - VkAccessFlags dstAccess) +void EventBarrierArray::addAdditionalStageAccess(const RefCountedEvent &waitEvent, + VkPipelineStageFlags dstStageMask, + VkAccessFlags dstAccess) { - ASSERT(waitEvent.valid()); - for (EventBarrier &barrier : mBarriers) { - // If the event is already in the waiting list, just add the new stageMask to the - // dstStageMask. Otherwise we will end up with two waitEvent calls that wait for the same - // VkEvent but for different dstStage and confuses VVL. if (barrier.hasEvent(waitEvent.getEvent().getHandle())) { barrier.addAdditionalStageAccess(dstStageMask, dstAccess); return; } } + UNREACHABLE(); +} +void EventBarrierArray::addMemoryEvent(Context *context, + const RefCountedEvent &waitEvent, + VkPipelineStageFlags dstStageMask, + VkAccessFlags dstAccess) +{ + ASSERT(waitEvent.valid()); VkAccessFlags accessMask; VkPipelineStageFlags stageFlags = GetRefCountedEventStageMask(context, waitEvent, &accessMask); - // Since this is used with WAW without layout change, dstStageMask should be the same as event's - // stageMask. Otherwise you should get into addImageEvent. + // This should come down as WAW without layout change, dstStageMask should be the same as + // event's stageMask. Otherwise you should get into addImageEvent. ASSERT(stageFlags == dstStageMask && accessMask == dstAccess); mBarriers.emplace_back(stageFlags, dstStageMask, accessMask, dstAccess, waitEvent.getEvent().getHandle()); @@ -138,30 +266,18 @@ void EventBarrierArray::addImageEvent(Context *context, { ASSERT(waitEvent.valid()); VkPipelineStageFlags srcStageFlags = GetRefCountedEventStageMask(context, waitEvent); - - mBarriers.emplace_back(); - EventBarrier &barrier = mBarriers.back(); - // VkCmdWaitEvent must uses the same stageMask as VkCmdSetEvent due to - // VUID-vkCmdWaitEvents-srcStageMask-01158 requirements. - barrier.mSrcStageMask = srcStageFlags; - // If there is an event, we use the waitEvent to do layout change. - barrier.mEvents.emplace_back(waitEvent.getEvent().getHandle()); - barrier.mDstStageMask = dstStageMask; - barrier.mImageMemoryBarriers.emplace_back(imageMemoryBarrier); + mBarriers.emplace_back(srcStageFlags, dstStageMask, waitEvent.getEvent().getHandle(), + imageMemoryBarrier); } void EventBarrierArray::execute(Renderer *renderer, PrimaryCommandBuffer *primary) { - if (mBarriers.empty()) - { - return; - } - - for (EventBarrier &barrier : mBarriers) + while (!mBarriers.empty()) { - barrier.execute(primary); + mBarriers.back().execute(primary); + mBarriers.pop_back(); } - mBarriers.clear(); + reset(); } void EventBarrierArray::addDiagnosticsString(std::ostringstream &out) const diff --git a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h index 19df7ad63f..6ce1e65d2e 100644 --- a/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h +++ b/src/libANGLE/renderer/vulkan/vk_ref_counted_event.h @@ -15,6 +15,7 @@ #include <queue> #include "common/PackedEnums.h" +#include "common/SimpleMutex.h" #include "common/debug.h" #include "libANGLE/renderer/serial_utils.h" #include "libANGLE/renderer/vulkan/vk_resource.h" @@ -45,6 +46,7 @@ struct EventAndLayout bool valid() const { return event.valid(); } Event event; ImageLayout imageLayout; + bool needsReset; }; // The VkCmdSetEvent is called after VkCmdEndRenderPass and all images that used at the given @@ -94,26 +96,21 @@ class RefCountedEvent final // Returns true if both points to the same underline object. bool operator==(const RefCountedEvent &other) const { return mHandle == other.mHandle; } - // Create VkEvent and associated it with given layout - void init(Context *context, ImageLayout layout); + // Create VkEvent and associated it with given layout. Returns true if success and false if + // failed. + bool init(Context *context, ImageLayout layout); - // Release one reference count to the underline Event object and destroy if this is the - // very last reference. - void release(VkDevice device) - { - if (mHandle != nullptr) - { - const bool isLastReference = mHandle->getAndReleaseRef() == 1; - if (isLastReference) - { - destroy(device); - } - else - { - mHandle = nullptr; - } - } - } + // Release one reference count to the underline Event object and destroy or recycle the handle + // to renderer's recycler if this is the very last reference. + void release(Renderer *renderer); + + // Release one reference count to the underline Event object and destroy or recycle the handle + // to the context share group's recycler if this is the very last reference. + void release(Context *context); + + // Destroy the event and mHandle. Caller must ensure there is no outstanding reference to the + // mHandle. + void destroy(VkDevice device); bool valid() const { return mHandle != nullptr; } @@ -131,18 +128,24 @@ class RefCountedEvent final return mHandle->get().imageLayout; } - private: - void destroy(VkDevice device) + bool needsReset() const { - ASSERT(mHandle != nullptr); - ASSERT(!mHandle->isReferenced()); - mHandle->get().event.destroy(device); - SafeDelete(mHandle); + ASSERT(valid()); + return mHandle->get().needsReset; } - AtomicRefCounted<EventAndLayout> *mHandle; + private: + // Release one reference count to the underline Event object and destroy or recycle the handle + // to the provided recycler if this is the very last reference. + friend class RefCountedEventRecycler; + friend class RefCountedEventsGarbage; + friend class RefCountedEventsGarbageRecycler; + template <typename RecyclerT> + void releaseImpl(Renderer *renderer, RecyclerT *recycler); + + RefCounted<EventAndLayout> *mHandle; }; -using RefCountedEventCollector = std::vector<RefCountedEvent>; +using RefCountedEventCollector = std::deque<RefCountedEvent>; // This class tracks a vector of RefcountedEvent garbage. For performance reason, instead of // individually tracking each VkEvent garbage, we collect all events that are accessed in the @@ -159,27 +162,30 @@ class RefCountedEventsGarbage final RefCountedEventsGarbage(const QueueSerial &queueSerial, RefCountedEventCollector &&refCountedEvents) - : mLifetime(queueSerial), mRefCountedEvents(std::move(refCountedEvents)) + : mQueueSerial(queueSerial), mRefCountedEvents(std::move(refCountedEvents)) { ASSERT(refCountedEvents.empty()); ASSERT(!mRefCountedEvents.empty()); } RefCountedEventsGarbage(RefCountedEventsGarbage &&other) - : mLifetime(other.mLifetime), mRefCountedEvents(std::move(other.mRefCountedEvents)) + : mQueueSerial(other.mQueueSerial), mRefCountedEvents(std::move(other.mRefCountedEvents)) {} RefCountedEventsGarbage &operator=(RefCountedEventsGarbage &&other) { ASSERT(mRefCountedEvents.empty()); - mLifetime = other.mLifetime; + mQueueSerial = other.mQueueSerial; mRefCountedEvents = std::move(other.mRefCountedEvents); return *this; } - bool destroyIfComplete(Renderer *renderer); - bool hasResourceUseSubmitted(Renderer *renderer) const; - VkDeviceSize getSize() const { return mRefCountedEvents.size(); } + void destroy(Renderer *renderer); + + // Check the queue serial and release the events to context if GPU finished. Note that release + // to context may end up recycle the object instead of destroy. Returns true if it is GPU + // finished. + bool releaseIfComplete(Renderer *renderer, RefCountedEventsGarbageRecycler *recycler); // Move event to the garbage list void add(RefCountedEvent &&event) { mRefCountedEvents.emplace_back(std::move(event)); } @@ -187,12 +193,8 @@ class RefCountedEventsGarbage final // Move the vector of events to the garbage list void add(RefCountedEventCollector &&events) { - mRefCountedEvents.reserve(mRefCountedEvents.size() + events.size()); - for (RefCountedEvent &event : events) - { - mRefCountedEvents.emplace_back(std::move(event)); - } - events.clear(); + mRefCountedEvents.insert(mRefCountedEvents.end(), events.begin(), events.end()); + ASSERT(events.empty()); } // Make a copy of event (which adds another refcount to the VkEvent) and add the copied event to @@ -207,17 +209,111 @@ class RefCountedEventsGarbage final bool empty() const { return mRefCountedEvents.empty(); } + size_t size() const { return mRefCountedEvents.size(); } + private: - ResourceUse mLifetime; + friend class RefCountedEventsGarbageRecycler; + QueueSerial mQueueSerial; RefCountedEventCollector mRefCountedEvents; }; +// Thread safe event recycler, protected by its own lock. +class RefCountedEventRecycler final +{ + public: + void recycle(RefCountedEvent &&garbageObject) + { + ASSERT(garbageObject.valid()); + ASSERT(!garbageObject.mHandle->isReferenced()); + std::lock_guard<angle::SimpleMutex> lock(mMutex); + mFreeStack.recycle(std::move(garbageObject)); + } + + void releaseOrRecycle(Renderer *renderer, RefCountedEventCollector &&eventCollector) + { + // Take lock once and then use event's releaseImpl function to directly recycle into the + // underlying recycling storage. + std::lock_guard<angle::SimpleMutex> lock(mMutex); + while (!eventCollector.empty()) + { + eventCollector.back().releaseImpl(renderer, &mFreeStack); + eventCollector.pop_back(); + } + } + + bool fetch(RefCountedEvent *outObject) + { + std::lock_guard<angle::SimpleMutex> lock(mMutex); + if (mFreeStack.empty()) + { + return false; + } + mFreeStack.fetch(outObject); + ASSERT(outObject->valid()); + ASSERT(!outObject->mHandle->isReferenced()); + return true; + } + + void destroy(VkDevice device) + { + std::lock_guard<angle::SimpleMutex> lock(mMutex); + mFreeStack.destroy(device); + } + + private: + angle::SimpleMutex mMutex; + Recycler<RefCountedEvent> mFreeStack; +}; + +// Not thread safe event garbage collection and recycler. Caller must ensure the thread safety. It +// is intended to use by ShareGroupVk which all access should already protected by share context +// lock. +class RefCountedEventsGarbageRecycler final +{ + public: + RefCountedEventsGarbageRecycler() : mGarbageCount(0) {} + ~RefCountedEventsGarbageRecycler(); + + // Release all garbage and free events. + void destroy(Renderer *renderer); + + // Walk the garbage list and move completed garbage to free list + void cleanup(Renderer *renderer); + + void collectGarbage(const QueueSerial &queueSerial, RefCountedEventCollector &&refCountedEvents) + { + mGarbageCount += refCountedEvents.size(); + mGarbageQueue.emplace(queueSerial, std::move(refCountedEvents)); + } + + void recycle(RefCountedEvent &&garbageObject) + { + ASSERT(garbageObject.valid()); + ASSERT(!garbageObject.mHandle->isReferenced()); + mFreeStack.recycle(std::move(garbageObject)); + } + + bool fetch(RefCountedEvent *outObject); + + size_t getGarbageCount() const { return mGarbageCount; } + + private: + Recycler<RefCountedEvent> mFreeStack; + std::queue<RefCountedEventsGarbage> mGarbageQueue; + size_t mGarbageCount; +}; + // This wraps data and API for vkCmdWaitEvent call class EventBarrier : angle::NonCopyable { public: EventBarrier() - : mSrcStageMask(0), mDstStageMask(0), mMemoryBarrierSrcAccess(0), mMemoryBarrierDstAccess(0) + : mSrcStageMask(0), + mDstStageMask(0), + mMemoryBarrierSrcAccess(0), + mMemoryBarrierDstAccess(0), + mImageMemoryBarrierCount(0), + mEvent(VK_NULL_HANDLE) {} EventBarrier(VkPipelineStageFlags srcStageMask, @@ -228,9 +324,11 @@ class EventBarrier : angle::NonCopyable : mSrcStageMask(srcStageMask), mDstStageMask(dstStageMask), mMemoryBarrierSrcAccess(srcAccess), - mMemoryBarrierDstAccess(dstAccess) + mMemoryBarrierDstAccess(dstAccess), + mImageMemoryBarrierCount(0), + mEvent(event) { - mEvents.push_back(event); + ASSERT(mEvent != VK_NULL_HANDLE); } EventBarrier(VkPipelineStageFlags srcStageMask, @@ -240,40 +338,37 @@ class EventBarrier : angle::NonCopyable : mSrcStageMask(srcStageMask), mDstStageMask(dstStageMask), mMemoryBarrierSrcAccess(0), - mMemoryBarrierDstAccess(0) + mMemoryBarrierDstAccess(0), + mImageMemoryBarrierCount(1), + mEvent(event), + mImageMemoryBarrier(imageMemoryBarrier) { - ASSERT(event != VK_NULL_HANDLE); - ASSERT(imageMemoryBarrier.pNext == nullptr); - mEvents.push_back(event); - mImageMemoryBarriers.push_back(imageMemoryBarrier); + ASSERT(mEvent != VK_NULL_HANDLE); + ASSERT(mImageMemoryBarrier.image != VK_NULL_HANDLE); + ASSERT(mImageMemoryBarrier.pNext == nullptr); } EventBarrier(EventBarrier &&other) { - mSrcStageMask = other.mSrcStageMask; - mDstStageMask = other.mDstStageMask; - mMemoryBarrierSrcAccess = other.mMemoryBarrierSrcAccess; - mMemoryBarrierDstAccess = other.mMemoryBarrierDstAccess; - std::swap(mEvents, other.mEvents); - std::swap(mImageMemoryBarriers, other.mImageMemoryBarriers); - other.mSrcStageMask = 0; - other.mDstStageMask = 0; - other.mMemoryBarrierSrcAccess = 0; - other.mMemoryBarrierDstAccess = 0; + mSrcStageMask = other.mSrcStageMask; + mDstStageMask = other.mDstStageMask; + mMemoryBarrierSrcAccess = other.mMemoryBarrierSrcAccess; + mMemoryBarrierDstAccess = other.mMemoryBarrierDstAccess; + mImageMemoryBarrierCount = other.mImageMemoryBarrierCount; + std::swap(mEvent, other.mEvent); + std::swap(mImageMemoryBarrier, other.mImageMemoryBarrier); + other.mSrcStageMask = 0; + other.mDstStageMask = 0; + other.mMemoryBarrierSrcAccess = 0; + other.mMemoryBarrierDstAccess = 0; + other.mImageMemoryBarrierCount = 0; } - ~EventBarrier() - { - ASSERT(mImageMemoryBarriers.empty()); - ASSERT(mEvents.empty()); - } + ~EventBarrier() {} - bool isEmpty() const - { - return mEvents.empty() && mImageMemoryBarriers.empty() && mMemoryBarrierDstAccess == 0; - } + bool isEmpty() const { return mEvent == VK_NULL_HANDLE; } - bool hasEvent(const VkEvent &event) const; + bool hasEvent(const VkEvent &event) const { return mEvent == event; } void addAdditionalStageAccess(VkPipelineStageFlags dstStageMask, VkAccessFlags dstAccess) { @@ -283,12 +378,6 @@ class EventBarrier : angle::NonCopyable void execute(PrimaryCommandBuffer *primary); - void reset() - { - mEvents.clear(); - mImageMemoryBarriers.clear(); - } - void addDiagnosticsString(std::ostringstream &out) const; private: @@ -297,8 +386,9 @@ class EventBarrier : angle::NonCopyable VkPipelineStageFlags mDstStageMask; VkAccessFlags mMemoryBarrierSrcAccess; VkAccessFlags mMemoryBarrierDstAccess; - std::vector<VkEvent> mEvents; - std::vector<VkImageMemoryBarrier> mImageMemoryBarriers; + uint32_t mImageMemoryBarrierCount; + VkEvent mEvent; + VkImageMemoryBarrier mImageMemoryBarrier; }; class EventBarrierArray final @@ -308,6 +398,11 @@ class EventBarrierArray final void execute(Renderer *renderer, PrimaryCommandBuffer *primary); + // Add the additional stageMask to the existing waitEvent. + void addAdditionalStageAccess(const RefCountedEvent &waitEvent, + VkPipelineStageFlags dstStageMask, + VkAccessFlags dstAccess); + void addMemoryEvent(Context *context, const RefCountedEvent &waitEvent, VkPipelineStageFlags dstStageMask, @@ -318,12 +413,12 @@ class EventBarrierArray final VkPipelineStageFlags dstStageMask, const VkImageMemoryBarrier &imageMemoryBarrier); - void reset() { mBarriers.clear(); } + void reset() { ASSERT(mBarriers.empty()); } void addDiagnosticsString(std::ostringstream &out) const; private: - std::vector<EventBarrier> mBarriers; + std::deque<EventBarrier> mBarriers; }; VkPipelineStageFlags GetRefCountedEventStageMask(Context *context, const RefCountedEvent &event); diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.cpp b/src/libANGLE/renderer/vulkan/vk_renderer.cpp index 4c4a49d719..983c90f433 100644 --- a/src/libANGLE/renderer/vulkan/vk_renderer.cpp +++ b/src/libANGLE/renderer/vulkan/vk_renderer.cpp @@ -161,6 +161,12 @@ bool IsXclipse() return strstr(modelName.c_str(), "SM-S901B") != nullptr; } +bool ShouldUseEventForImageBarrier() +{ + // Disabled for now while performance is under investigation + return false; +} + bool StrLess(const char *a, const char *b) { return strcmp(a, b) < 0; @@ -293,6 +299,12 @@ constexpr const char *kNoListRestartSkippedMessages[] = { "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252", }; +// VVL appears has a bug tracking stageMask on VkEvent with secondary command buffer. +// https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7849 +constexpr const char *kSkippedMessagesWithVulkanSecondaryCommandBuffer[] = { + "VUID-vkCmdWaitEvents-srcStageMask-parameter", +}; + // Some syncval errors are resolved in the presence of the NONE load or store render pass ops. For // those, ANGLE makes no further attempt to resolve them and expects vendor support for the // extensions instead. The list of skipped messages is split based on this support. @@ -1494,8 +1506,7 @@ Renderer::~Renderer() {} bool Renderer::hasSharedGarbage() { - return !mSharedGarbageList.empty() || !mSuballocationGarbageList.empty() || - !mRefCountedEventGarbageList.empty(); + return !mSharedGarbageList.empty() || !mSuballocationGarbageList.empty(); } void Renderer::onDestroy(vk::Context *context) @@ -1513,6 +1524,8 @@ void Renderer::onDestroy(vk::Context *context) ASSERT(!hasSharedGarbage()); ASSERT(mOrphanedBufferBlockList.empty()); + mRefCountedEventRecycler.destroy(mDevice); + for (OneOffCommandPool &oneOffCommandPool : mOneOffCommandPoolMap) { oneOffCommandPool.destroy(mDevice); @@ -1884,7 +1897,11 @@ angle::Result Renderer::initialize(vk::Context *context, // Fine grain control of validation layer features const char *name = "VK_LAYER_KHRONOS_validation"; const VkBool32 setting_validate_core = VK_TRUE; - const VkBool32 setting_validate_sync = IsAndroid() ? VK_FALSE : VK_TRUE; + // SyncVal is very slow (https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7285) + // for VkEvent which causes a few tests fail on the bots. Disable syncVal if VkEvent is enabled + // for now. + const VkBool32 setting_validate_sync = + IsAndroid() || ShouldUseEventForImageBarrier() ? VK_FALSE : VK_TRUE; const VkBool32 setting_thread_safety = VK_TRUE; // http://anglebug.com/7050 - Shader validation caching is broken on Android const VkBool32 setting_check_shaders = IsAndroid() ? VK_FALSE : VK_TRUE; @@ -3559,10 +3576,7 @@ angle::Result Renderer::createDeviceAndQueue(vk::Context *context, uint32_t queu initDeviceExtensionEntryPoints(); - vk::DeviceQueueMap graphicsQueueMap = - queueFamily.initializeQueueMap(mDevice, enableProtectedContent, 0, queueCount); - - ANGLE_TRY(mCommandQueue.init(context, graphicsQueueMap)); + ANGLE_TRY(mCommandQueue.init(context, queueFamily, enableProtectedContent, queueCount)); ANGLE_TRY(mCommandProcessor.init()); if (mFeatures.forceMaxUniformBufferSize16KB.enabled) @@ -3645,6 +3659,16 @@ void Renderer::initializeValidationMessageSuppressions() kNoListRestartSkippedMessages + ArraySize(kNoListRestartSkippedMessages)); } + if (getFeatures().useVkEventForImageBarrier.enabled && + (!vk::OutsideRenderPassCommandBuffer::ExecutesInline() || + !vk::RenderPassCommandBuffer::ExecutesInline())) + { + mSkippedValidationMessages.insert( + mSkippedValidationMessages.end(), kSkippedMessagesWithVulkanSecondaryCommandBuffer, + kSkippedMessagesWithVulkanSecondaryCommandBuffer + + ArraySize(kSkippedMessagesWithVulkanSecondaryCommandBuffer)); + } + // Build the list of syncval errors that are currently expected and should be skipped. mSkippedSyncvalMessages.insert(mSkippedSyncvalMessages.end(), kSkippedSyncvalMessages, kSkippedSyncvalMessages + ArraySize(kSkippedSyncvalMessages)); @@ -4046,9 +4070,6 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, return; } - constexpr uint32_t kPixel2DriverWithRelaxedPrecision = 0x801EA000; - constexpr uint32_t kPixel4DriverWithWorkingSpecConstSupport = 0x80201000; - const bool isAMD = IsAMD(mPhysicalDeviceProperties.vendorID); const bool isApple = IsAppleGPU(mPhysicalDeviceProperties.vendorID); const bool isARM = IsARM(mPhysicalDeviceProperties.vendorID); @@ -4080,7 +4101,11 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, isARM && getPhysicalDeviceProperties().limits.maxDrawIndirectCount <= 1; // Parse the ARM driver version to be readable/comparable const ARMDriverVersion armDriverVersion = - ParseARMDriverVersion(mPhysicalDeviceProperties.driverVersion); + ParseARMVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion); + + // Parse the Qualcomm driver version. + const QualcommDriverVersion qualcommDriverVersion = + ParseQualcommVulkanDriverVersion(mPhysicalDeviceProperties.driverVersion); // Parse the Intel driver version. (Currently it only supports the Windows driver.) const IntelDriverVersion intelDriverVersion = @@ -4435,10 +4460,11 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, enablePreRotateSurfaces, IsAndroid()); // http://anglebug.com/3078 + // Precision qualifiers are disabled for Pixel 2 before the driver included relaxed precision. ANGLE_FEATURE_CONDITION( &mFeatures, enablePrecisionQualifiers, !(IsPixel2(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID) && - (mPhysicalDeviceProperties.driverVersion < kPixel2DriverWithRelaxedPrecision)) && + (qualcommDriverVersion < QualcommDriverVersion(512, 490, 0))) && !IsPixel4(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID)); // http://anglebug.com/7488 @@ -4468,7 +4494,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Prefer driver uniforms over specialization constants in the following: // - // - Older Qualcomm drivers where specialization constants severly degrade the performance of + // - Older Qualcomm drivers where specialization constants severely degrade the performance of // pipeline creation. http://issuetracker.google.com/173636783 // - ARM hardware // - Imagination hardware @@ -4476,8 +4502,7 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // ANGLE_FEATURE_CONDITION( &mFeatures, preferDriverUniformOverSpecConst, - (isQualcommProprietary && - mPhysicalDeviceProperties.driverVersion < kPixel4DriverWithWorkingSpecConstSupport) || + (isQualcommProprietary && qualcommDriverVersion < QualcommDriverVersion(512, 513, 0)) || isARM || isPowerVR || isSwiftShader); // The compute shader used to generate mipmaps needs - @@ -4560,8 +4585,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // vkCmdClearAttachments races with draw calls on Qualcomm hardware as observed on Pixel2 and // Pixel4. https://issuetracker.google.com/issues/166809097 - ANGLE_FEATURE_CONDITION(&mFeatures, preferDrawClearOverVkCmdClearAttachments, - isQualcommProprietary); + ANGLE_FEATURE_CONDITION( + &mFeatures, preferDrawClearOverVkCmdClearAttachments, + isQualcommProprietary && qualcommDriverVersion < QualcommDriverVersion(512, 762, 12)); // r32f image emulation is done unconditionally so VK_FORMAT_FEATURE_STORAGE_*_ATOMIC_BIT is not // required. @@ -4650,10 +4676,10 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // Important games are not checking supported extensions properly, and are confusing the // GL_EXT_shader_framebuffer_fetch_non_coherent as the GL_EXT_shader_framebuffer_fetch - // extension. Therefore, don't enable the extension on Arm and Qualcomm by default. + // extension. Therefore, don't enable the extension on Android by default. // https://issuetracker.google.com/issues/186643966 - ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetchNonCoherent, - (IsAndroid() && !(isARM || isQualcomm)) || isSwiftShader); + // https://issuetracker.google.com/issues/340665604 + ANGLE_FEATURE_CONDITION(&mFeatures, supportsShaderFramebufferFetchNonCoherent, isSwiftShader); // On tile-based renderers, breaking the render pass is costly. Changing into and out of // framebuffer fetch causes the render pass to break so that the layout of the color attachments @@ -4676,15 +4702,18 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, // usable. Additionally, the following platforms don't support INPUT_ATTACHMENT usage for the // swapchain, so they are excluded: // - // - Intel + // - Intel on windows + // - Intel on Linux before mesa 22.0 // // The above platforms are not excluded if behind MESA Virtio-GPU Venus driver since WSI is // implemented with external memory there. // // Without VK_GOOGLE_surfaceless_query, there is no way to automatically deduce this support. + const bool isMesaAtLeast22_0_0 = mesaVersion.major >= 22; ANGLE_FEATURE_CONDITION( &mFeatures, emulateAdvancedBlendEquations, - !mFeatures.supportsBlendOperationAdvanced.enabled && (isVenus || !isIntel)); + !mFeatures.supportsBlendOperationAdvanced.enabled && + (isVenus || !isIntel || (isIntel && IsLinux() && isMesaAtLeast22_0_0))); // http://anglebug.com/6933 // Android expects VkPresentRegionsKHR rectangles with a bottom-left origin, while spec @@ -5049,9 +5078,9 @@ void Renderer::initFeatures(const vk::ExtensionNameList &deviceExtensionNames, ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalFormatResolve, false); #endif - // Disable use of VkCmdWaitEvent for image barriers for now. - // https://issuetracker.google.com/336844257 - ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForImageBarrier, false); + // initialize() is disabling syncval if event is used, which comes before feature flag is set. + // Use ShouldUseEventForImageBarrier to enable/disable event for certain config if needed. + ANGLE_FEATURE_CONDITION(&mFeatures, useVkEventForImageBarrier, ShouldUseEventForImageBarrier()); // Disable memory report feature overrides if extension is not supported. if ((mFeatures.logMemoryReportCallbacks.enabled || mFeatures.logMemoryReportStats.enabled) && @@ -5506,8 +5535,6 @@ void Renderer::cleanupGarbage() // Note: do this after clean up mSuballocationGarbageList so that we will have more chances to // find orphaned blocks being empty. mOrphanedBufferBlockList.pruneEmptyBufferBlocks(this); - // Clean up event garbages - mRefCountedEventGarbageList.cleanupSubmittedGarbage(this); } void Renderer::cleanupPendingSubmissionGarbage() @@ -5515,7 +5542,6 @@ void Renderer::cleanupPendingSubmissionGarbage() // Check if pending garbage is still pending. If not, move them to the garbage list. mSharedGarbageList.cleanupUnsubmittedGarbage(this); mSuballocationGarbageList.cleanupUnsubmittedGarbage(this); - mRefCountedEventGarbageList.cleanupUnsubmittedGarbage(this); } void Renderer::onNewValidationMessage(const std::string &message) diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.h b/src/libANGLE/renderer/vulkan/vk_renderer.h index 228da259fd..da7bb390f3 100644 --- a/src/libANGLE/renderer/vulkan/vk_renderer.h +++ b/src/libANGLE/renderer/vulkan/vk_renderer.h @@ -228,6 +228,15 @@ class Renderer : angle::NonCopyable { return mQueueFamilyProperties[mCurrentQueueFamilyIndex]; } + const DeviceQueueIndex getDeviceQueueIndex(egl::ContextPriority priority) const + { + return mCommandQueue.getDeviceQueueIndex(priority); + } + const DeviceQueueIndex getDefaultDeviceQueueIndex() const + { + // By default it will always use medium priority + return mCommandQueue.getDeviceQueueIndex(egl::ContextPriority::Medium); + } const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; } @@ -277,7 +286,6 @@ class Renderer : angle::NonCopyable { return mCommandQueue.getDriverPriority(priority); } - ANGLE_INLINE uint32_t getDeviceQueueIndex() { return mCommandQueue.getDeviceQueueIndex(); } VkQueue getQueue(egl::ContextPriority priority) { return mCommandQueue.getQueue(priority); } @@ -339,14 +347,6 @@ class Renderer : angle::NonCopyable mSuballocationGarbageList.add(this, std::move(garbage)); } - void collectRefCountedEventsGarbage(const QueueSerial &queueSerial, - vk::RefCountedEventCollector &&refCountedEvents) - { - ASSERT(!refCountedEvents.empty()); - vk::RefCountedEventsGarbage garbage(queueSerial, std::move(refCountedEvents)); - mRefCountedEventGarbageList.add(this, std::move(garbage)); - } - angle::Result getPipelineCache(vk::Context *context, vk::PipelineCacheAccess *pipelineCacheOut); angle::Result mergeIntoPipelineCache(vk::Context *context, const vk::PipelineCache &pipelineCache); @@ -748,6 +748,10 @@ class Renderer : angle::NonCopyable return mPipelineCacheGraphDumpPath.c_str(); } + vk::RefCountedEventRecycler *getRefCountedEventRecycler() { return &mRefCountedEventRecycler; } + + std::thread::id getCommandProcessorThreadId() const { return mCommandProcessor.getThreadId(); } + private: angle::Result setupDevice(vk::Context *context, const angle::FeatureOverrides &featureOverrides, @@ -957,8 +961,8 @@ class Renderer : angle::NonCopyable vk::SharedGarbageList<vk::BufferSuballocationGarbage> mSuballocationGarbageList; // Holds orphaned BufferBlocks when ShareGroup gets destroyed vk::BufferBlockGarbageList mOrphanedBufferBlockList; - // Holds RefCountedEvent garbage - vk::SharedGarbageList<vk::RefCountedEventsGarbage> mRefCountedEventGarbageList; + // Holds RefCountedEvent that are free and ready to reuse + vk::RefCountedEventRecycler mRefCountedEventRecycler; VkDeviceSize mPendingGarbageSizeLimit; diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp index 3c4390f7a1..0699e95e83 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.cpp +++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp @@ -370,7 +370,9 @@ VkImageAspectFlags GetFormatAspectFlags(const angle::Format &format) } // Context implementation. -Context::Context(Renderer *renderer) : mRenderer(renderer), mPerfCounters{} {} +Context::Context(Renderer *renderer) + : mRenderer(renderer), mShareGroupRefCountedEventsGarbageRecycler(nullptr), mPerfCounters{} +{} Context::~Context() {} diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h index dc4ebdf9d6..0df93a457f 100644 --- a/src/libANGLE/renderer/vulkan/vk_utils.h +++ b/src/libANGLE/renderer/vulkan/vk_utils.h @@ -132,6 +132,65 @@ class Renderer; // Used for memory allocation tracking. enum class MemoryAllocationType; +// Encapsulate the graphics family index and VkQueue index (as seen in vkGetDeviceQueue API +// arguments) into one integer so that we can easily pass around without introduce extra overhead.. +class DeviceQueueIndex final +{ + public: + constexpr DeviceQueueIndex() + : mFamilyIndex(kInvalidQueueFamilyIndex), mQueueIndex(kInvalidQueueIndex) + {} + constexpr DeviceQueueIndex(uint32_t familyIndex) + : mFamilyIndex((int8_t)familyIndex), mQueueIndex(kInvalidQueueIndex) + { + ASSERT(static_cast<uint32_t>(mFamilyIndex) == familyIndex); + } + DeviceQueueIndex(uint32_t familyIndex, uint32_t queueIndex) + : mFamilyIndex((int8_t)familyIndex), mQueueIndex((int8_t)queueIndex) + { + // Ensure the value we actually don't truncate the useful bits. + ASSERT(static_cast<uint32_t>(mFamilyIndex) == familyIndex); + ASSERT(static_cast<uint32_t>(mQueueIndex) == queueIndex); + } + DeviceQueueIndex(const DeviceQueueIndex &other) { *this = other; } + + DeviceQueueIndex &operator=(const DeviceQueueIndex &other) + { + mValue = other.mValue; + return *this; + } + + constexpr uint32_t familyIndex() const { return mFamilyIndex; } + constexpr uint32_t queueIndex() const { return mQueueIndex; } + + bool operator==(const DeviceQueueIndex &other) const { return mValue == other.mValue; } + bool operator!=(const DeviceQueueIndex &other) const { return mValue != other.mValue; } + + private: + static constexpr int8_t kInvalidQueueFamilyIndex = -1; + static constexpr int8_t kInvalidQueueIndex = -1; + // The expectation is that these indices are small numbers that could easily fit into int8_t. + // int8_t is used instead of uint8_t because we need to handle VK_QUEUE_FAMILY_FOREIGN_EXT and + // VK_QUEUE_FAMILY_EXTERNAL properly which are essentially are negative values. + union + { + struct + { + int8_t mFamilyIndex; + int8_t mQueueIndex; + }; + uint16_t mValue; + }; +}; +static constexpr DeviceQueueIndex kInvalidDeviceQueueIndex = DeviceQueueIndex(); +static constexpr DeviceQueueIndex kForeignDeviceQueueIndex = + DeviceQueueIndex(VK_QUEUE_FAMILY_FOREIGN_EXT); +static constexpr DeviceQueueIndex kExternalDeviceQueueIndex = + DeviceQueueIndex(VK_QUEUE_FAMILY_EXTERNAL); +static_assert(kForeignDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_FOREIGN_EXT); +static_assert(kExternalDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_EXTERNAL); +static_assert(kInvalidDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_IGNORED); + // A packed attachment index interface with vulkan API class PackedAttachmentIndex final { @@ -278,6 +337,7 @@ class [[nodiscard]] ScopedQueueSerialIndex final : angle::NonCopyable QueueSerialIndexAllocator *mIndexAllocator; }; +class RefCountedEventsGarbageRecycler; // Abstracts error handling. Implemented by ContextVk for GL, DisplayVk for EGL, worker threads, // CLContextVk etc. class Context : angle::NonCopyable @@ -296,9 +356,17 @@ class Context : angle::NonCopyable const angle::VulkanPerfCounters &getPerfCounters() const { return mPerfCounters; } angle::VulkanPerfCounters &getPerfCounters() { return mPerfCounters; } + RefCountedEventsGarbageRecycler *getRefCountedEventsGarbageRecycler() + { + return mShareGroupRefCountedEventsGarbageRecycler; + } + const DeviceQueueIndex &getDeviceQueueIndex() const { return mDeviceQueueIndex; } protected: Renderer *const mRenderer; + // Stash the ShareGroupVk's RefCountedEventRecycler here ImageHelper to conveniently access + RefCountedEventsGarbageRecycler *mShareGroupRefCountedEventsGarbageRecycler; + DeviceQueueIndex mDeviceQueueIndex; angle::VulkanPerfCounters mPerfCounters; }; @@ -664,6 +732,12 @@ class RefCounted : angle::NonCopyable mRefCount--; } + uint32_t getAndReleaseRef() + { + ASSERT(isReferenced()); + return mRefCount--; + } + bool isReferenced() const { return mRefCount != 0; } T &get() { return mObject; } @@ -702,9 +776,7 @@ class AtomicRefCounted : angle::NonCopyable unsigned int getAndReleaseRef() { ASSERT(isReferenced()); - // This is used by RefCountedEvent which will decrement in clean up thread, so - // memory_order_acq_rel is needed. - return mRefCount.fetch_sub(1, std::memory_order_acq_rel); + return mRefCount.fetch_sub(1, std::memory_order_relaxed); } bool isReferenced() const { return mRefCount.load(std::memory_order_relaxed) != 0; } @@ -907,7 +979,7 @@ class Recycler final : angle::NonCopyable bool empty() const { return mObjectFreeList.empty(); } private: - std::vector<T> mObjectFreeList; + std::deque<T> mObjectFreeList; }; ANGLE_ENABLE_STRUCT_PADDING_WARNINGS diff --git a/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp b/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp index f2b2f5fcec..a35a686bc2 100644 --- a/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp +++ b/src/libANGLE/renderer/wgpu/DeviceWgpu.cpp @@ -29,11 +29,6 @@ egl::Error DeviceWgpu::getAttribute(const egl::Display *display, EGLint attribut return egl::EglBadAccess(); } -EGLint DeviceWgpu::getType() -{ - return 0; -} - void DeviceWgpu::generateExtensions(egl::DeviceExtensions *outExtensions) const {} } // namespace rx diff --git a/src/libANGLE/renderer/wgpu/DeviceWgpu.h b/src/libANGLE/renderer/wgpu/DeviceWgpu.h index a4c799bf2e..b8966a3119 100644 --- a/src/libANGLE/renderer/wgpu/DeviceWgpu.h +++ b/src/libANGLE/renderer/wgpu/DeviceWgpu.h @@ -25,7 +25,6 @@ class DeviceWgpu : public DeviceImpl egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override; - EGLint getType() override; void generateExtensions(egl::DeviceExtensions *outExtensions) const override; }; diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp index 18404cc50a..4a3cbed55b 100644 --- a/src/libANGLE/validationEGL.cpp +++ b/src/libANGLE/validationEGL.cpp @@ -6416,8 +6416,14 @@ bool ValidateQueryDeviceAttribEXT(const ValidationContext *val, switch (attribute) { case EGL_D3D11_DEVICE_ANGLE: + if (!device->getExtensions().deviceD3D11) + { + val->setError(EGL_BAD_ATTRIBUTE); + return false; + } + break; case EGL_D3D9_DEVICE_ANGLE: - if (!device->getExtensions().deviceD3D || device->getType() != attribute) + if (!device->getExtensions().deviceD3D9) { val->setError(EGL_BAD_ATTRIBUTE); return false; diff --git a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp index b68fd658bb..4760f088eb 100644 --- a/src/libGLESv2/entry_points_gles_2_0_autogen.cpp +++ b/src/libGLESv2/entry_points_gles_2_0_autogen.cpp @@ -121,7 +121,7 @@ void GL_APIENTRY GL_BindBuffer(GLenum target, GLuint buffer) { BufferBinding targetPacked = PackParam<BufferBinding>(target); BufferID bufferPacked = PackParam<BufferID>(buffer); - SCOPED_SHARE_CONTEXT_LOCK(context); + bool isCallValid = (context->skipValidation() || ValidateBindBuffer(context, angle::EntryPoint::GLBindBuffer, targetPacked, bufferPacked)); diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt index f5bdcba673..31296ecd29 100644 --- a/src/tests/angle_end2end_tests_expectations.txt +++ b/src/tests/angle_end2end_tests_expectations.txt @@ -199,6 +199,7 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 7866 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinary/* = SKIP 7866 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsRestoredWithProgramBinaryTwice/* = SKIP 7866 WIN INTEL VULKAN : VulkanPerformanceCounterTest.PipelineCacheIsWarmedUpAtLinkTime/* = SKIP +342557702 WIN INTEL VULKAN : StateChangeTestES3.RasterizerDiscard/ES3_Vulkan_NoSupportsExtendedDynamicState2 = SKIP // vk_icdNegotiateLoaderICDInterfaceVersion crashes (possibly Mesa bug?) 8179 LINUX INTEL VULKAN : RGBTextureBufferTestES31.* = SKIP 8179 LINUX INTEL VULKAN : TextureBufferTestES31.TexBufferFormatMismatch/* = SKIP @@ -458,7 +459,6 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 6480 PIXEL4ORXL GLES : RobustResourceInitTestES3.CheckMultisampleDepthStencilRenderbufferIsCleared/* = SKIP 5981 PIXEL4ORXL GLES : SimpleStateChangeTestES31.ClearThenSampleWithCompute/* = SKIP 5981 PIXEL4ORXL GLES : SimpleStateChangeTestES31.InvalidateThenStorageWriteThenBlend/* = SKIP -6744 PIXEL4ORXL GLES : SimpleStateChangeTestES3.OutOfBoundsByteAttribute/* = SKIP 5981 PIXEL4ORXL GLES : SimpleStateChangeTestES31.TransformFeedbackThenReadWithCompute/* = SKIP 5981 PIXEL4ORXL GLES : Texture3DTestES2.DefineTexture2DArrayShouldFail/* = SKIP 5981 PIXEL4ORXL GLES : Texture3DTestES2.CopySubImageAlpha/* = SKIP @@ -506,7 +506,6 @@ b/273271471 WIN INTEL VULKAN : ShaderAlgorithmTest.rgb_to_hsl_vertex_shader/* = 5981 PIXEL4ORXL VULKAN : PointSpriteTest.TrianglesNotTreatedAsPointSprites/* = SKIP 5981 PIXEL4ORXL VULKAN : ProgramBinaryTransformFeedbackTest.GetTransformFeedbackVarying/* = SKIP 5981 PIXEL4ORXL VULKAN : TransformFeedbackTestIOBlocks.Interleaved/* = SKIP -6744 PIXEL4ORXL VULKAN : SimpleStateChangeTestES3.OutOfBoundsByteAttribute/* = SKIP 6843 PIXEL4ORXL VULKAN : ImageTest.SourceYUVAHBTargetExternalRGBSampleInitData/* = SKIP 6843 PIXEL4ORXL VULKAN : ImageTestES3.SourceYUVAHBTargetExternalYUVSampleLinearFiltering/* = SKIP 7108 PIXEL4ORXL VULKAN : ImageTestES3.SourceAHBMipTarget2DMip/* = SKIP @@ -1211,7 +1210,6 @@ b/267953710 GALAXYS22 VULKAN : VulkanPerformanceCounterTest_ES31.ColorMaskedFram 8185 GALAXYQUALCOMM VULKAN : RobustResourceInitTest.MaskedStencilClear/* = SKIP 8185 GALAXYQUALCOMM VULKAN : RobustResourceInitTestES3.MaskedStencilClearBuffer/* = SKIP 8185 GALAXYQUALCOMM VULKAN : SampleVariablesTest.SamplePosition/* = SKIP -8185 GALAXYQUALCOMM VULKAN : SimpleStateChangeTestES3.OutOfBoundsByteAttribute/* = SKIP 8185 GALAXYQUALCOMM VULKAN : StateChangeTestES3.StencilReferenceAndCompareMask/* = SKIP 8185 GALAXYQUALCOMM VULKAN : Texture2DTestES3.TexImageWithStencilData/* = SKIP 8185 GALAXYQUALCOMM VULKAN : Texture2DTestES3.TexImageWithStencilPBO/* = SKIP diff --git a/src/tests/deqp_support/deqp.gni b/src/tests/deqp_support/deqp.gni index 65de2dffd4..c65d9ba894 100644 --- a/src/tests/deqp_support/deqp.gni +++ b/src/tests/deqp_support/deqp.gni @@ -869,6 +869,10 @@ deqp_khr_common_sources = [ "$deqp_path/external/openglcts/modules/common/glcAggressiveShaderOptimizationsTests.hpp", "$deqp_path/external/openglcts/modules/common/glcBlendEquationAdvancedTests.cpp", "$deqp_path/external/openglcts/modules/common/glcBlendEquationAdvancedTests.hpp", + "$deqp_path/external/openglcts/modules/common/glcBufferObjectsTests.cpp", + "$deqp_path/external/openglcts/modules/common/glcBufferObjectsTests.hpp", + "$deqp_path/external/openglcts/modules/common/glcClipDistance.cpp", + "$deqp_path/external/openglcts/modules/common/glcClipDistance.hpp", "$deqp_path/external/openglcts/modules/common/glcCompressedFormatTests.cpp", "$deqp_path/external/openglcts/modules/common/glcCompressedFormatTests.hpp", "$deqp_path/external/openglcts/modules/common/glcCompressedFormatTests_data.inl", @@ -886,6 +890,8 @@ deqp_khr_common_sources = [ "$deqp_path/external/openglcts/modules/common/glcContext.hpp", "$deqp_path/external/openglcts/modules/common/glcContextFlagsTests.cpp", "$deqp_path/external/openglcts/modules/common/glcContextFlagsTests.hpp", + "$deqp_path/external/openglcts/modules/common/glcCullDistance.cpp", + "$deqp_path/external/openglcts/modules/common/glcCullDistance.hpp", "$deqp_path/external/openglcts/modules/common/glcExposedExtensionsTests.cpp", "$deqp_path/external/openglcts/modules/common/glcExposedExtensionsTests.hpp", "$deqp_path/external/openglcts/modules/common/glcExtTokens.cpp", @@ -986,6 +992,8 @@ deqp_khr_common_sources = [ "$deqp_path/external/openglcts/modules/common/glcTextureRepeatModeTests.hpp", "$deqp_path/external/openglcts/modules/common/glcUniformBlockCase.cpp", "$deqp_path/external/openglcts/modules/common/glcUniformBlockCase.hpp", + "$deqp_path/external/openglcts/modules/common/glcUniformBlockNegativeTests.cpp", + "$deqp_path/external/openglcts/modules/common/glcUniformBlockNegativeTests.hpp", "$deqp_path/external/openglcts/modules/common/glcUniformBlockTests.cpp", "$deqp_path/external/openglcts/modules/common/glcUniformBlockTests.hpp", "$deqp_path/external/openglcts/modules/common/glcViewportArrayTests.cpp", @@ -1056,12 +1064,8 @@ deqp_khr_test_module_headers = [ ] deqp_khr_gl_sources = [ - "$deqp_path/external/openglcts/modules/gl/gl3cClipDistance.cpp", - "$deqp_path/external/openglcts/modules/gl/gl3cClipDistance.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cCommonBugsTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl3cCommonBugsTests.hpp", - "$deqp_path/external/openglcts/modules/gl/gl3cCullDistanceTests.cpp", - "$deqp_path/external/openglcts/modules/gl/gl3cCullDistanceTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cGLSLnoperspectiveTests.cpp", "$deqp_path/external/openglcts/modules/gl/gl3cGLSLnoperspectiveTests.hpp", "$deqp_path/external/openglcts/modules/gl/gl3cGPUShader5Tests.cpp", diff --git a/src/tests/deqp_support/deqp_gl46_test_expectations.txt b/src/tests/deqp_support/deqp_gl46_test_expectations.txt index 3deca78873..d05228700f 100644 --- a/src/tests/deqp_support/deqp_gl46_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gl46_test_expectations.txt @@ -81,3 +81,4 @@ 7566 SWIFTSHADER UBSAN : KHR-GL46.shader_bitfield_operation.bitfieldInsert.int_3 = SKIP +8693 SWIFTSHADER : KHR-GL46.buffer_objects.* = FAIL diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt index 33e3936aed..8ed4da8f64 100644 --- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt @@ -365,3 +365,12 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.texture*cube* = SKIP b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.random.* = SKIP b/328156792 PINEAPPLE VULKAN : dEQP-GLES2.functional.uniform_api.value.assigned.* = SKIP +// BGRA failures +8692 : dEQP-GLES2.functional.fbo.completeness.renderable.renderbuffer*bgra = FAIL +8692 : dEQP-GLES2.functional.fbo.render.color*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.depth*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.*_colorbuffer*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.*_depthbuffer*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.*_stencilbuffer*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.resize*bgra* = FAIL +8692 : dEQP-GLES2.functional.fbo.render.stencil*bgra* = FAIL diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt index a11c78a32a..a0bacc6c64 100644 --- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt @@ -179,20 +179,8 @@ b/266710445 WIN OPENGL NVIDIA : dEQP-GLES31.functional.image_load_store.buffer.a 3886 VULKAN NVIDIA : dEQP-GLES31.functional.image_load_store.3d.*single_layer = SKIP // Emulated advanced blend equations (only Nvidia and SwiftShader support the Vulkan extension): -3586 AMD VULKAN : dEQP-GLES31.functional.blend_equation_advanced.msaa.* = FAIL 3586 INTEL VULKAN : dEQP-GLES31.functional.blend_equation_advanced.msaa.* = FAIL 3586 PIXEL4ORXL VULKAN : dEQP-GLES31.functional.blend_equation_advanced.msaa.* = FAIL -//// -//// AMD Vulkan expectations -//// - -// Cannot support the per-sample shading when gl_SampleID or gl_SamplePosition: -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit*_per_sample.multisample_*_1 = FAIL -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit*_per_sample.multisample_*_2 = FAIL -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit*_per_sample.multisample_*_4 = FAIL -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit*_per_sample.multisample_*_8 = FAIL -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_two_samples.multisample_*_4 = FAIL -3588 VULKAN AMD : dEQP-GLES31.functional.shaders.sample_variables.sample_mask_in.bit_count_per_two_samples.multisample_*_8 = FAIL //// //// Android (i.e. Pixel*) Vulkan expectations @@ -208,16 +196,11 @@ b/266710445 WIN OPENGL NVIDIA : dEQP-GLES31.functional.image_load_store.buffer.a 4371 SWIFTSHADER : dEQP-GLES31.functional.shaders.implicit_conversions.* = FAIL // Desktop cards without native etc support, angle emulated format fails -5276 AMD VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_eac* = FAIL -5276 AMD VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_etc* = FAIL -5276 AMD VULKAN : dEQP-GLES31.functional.copy_image.mixed.*eac* = FAIL 5276 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_eac* = FAIL 5276 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_etc* = FAIL 5276 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.mixed.*eac* = FAIL // Copy image tests fail on desktop cards where ASTC is emulated -7415 AMD VULKAN : dEQP-GLES31.functional.copy_image.mixed.*astc* = FAIL -7415 AMD VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_astc* = FAIL 7415 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.mixed.*astc* = FAIL 7415 NVIDIA VULKAN : dEQP-GLES31.functional.copy_image.compressed.viewclass_astc* = FAIL diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_test_expectations.txt index 78c97197fe..55668810e7 100644 --- a/src/tests/deqp_support/deqp_gles3_test_expectations.txt +++ b/src/tests/deqp_support/deqp_gles3_test_expectations.txt @@ -859,3 +859,7 @@ b/328156792 PINEAPPLE VULKAN : dEQP-GLES3.functional.uniform_api.value.assigned. 4140 VULKAN : dEQP-GLES3.functional.transform_feedback.array_element.interleaved.* = FAIL 4140 VULKAN : dEQP-GLES3.functional.transform_feedback.array_element.separate.* = FAIL 4140 VULKAN : dEQP-GLES3.functional.transform_feedback.random.* = FAIL + +// BGRA failures +8692 : dEQP-GLES3.functional.fbo.completeness.renderable.renderbuffer*bgra = FAIL +8692 MAC : dEQP-GLES3.functional.texture.filtering.2d_array.formats.bgra* = FAIL
\ No newline at end of file diff --git a/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt index 211b4e5d5e..6959e7e4ec 100644 --- a/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt +++ b/src/tests/deqp_support/deqp_khr_gles32_test_expectations.txt @@ -95,17 +95,12 @@ 3577 VULKAN PIXEL4ORXL : KHR-GLES32.core.gpu_shader5.*clamp*_edge = SKIP // Desktop cards without native etc support -5276 AMD VULKAN LINUX : KHR-GLES32.core.texture_cube_map_array.etc2_texture = FAIL -5276 AMD VULKAN WIN : KHR-GLES32.core.texture_cube_map_array.etc2_texture = FAIL 5276 NVIDIA VULKAN : KHR-GLES32.core.texture_cube_map_array.etc2_texture = FAIL // Validation errors 6441 VULKAN NVIDIA : KHR-GLES32.core.compressed_format.api.copy_compressed_to_uncompressed = FAIL 6441 VULKAN NVIDIA : KHR-GLES32.core.compressed_format.api.copy_uncompressed_to_compressed = FAIL 6441 VULKAN NVIDIA : KHR-GLES32.core.compressed_format.api.copy_compressed_to_compressed = FAIL -// Looks like test error where ASTC support is not queried -6441 VULKAN NVIDIA : KHR-GLES32.core.compressed_format.format.*astc* = FAIL -6441 VULKAN AMD : KHR-GLES32.core.compressed_format.format.*astc* = FAIL // Pixel 4 expectations. 5990 PIXEL4ORXL VULKAN : KHR-GLES32.core.draw_buffers_indexed.color_masks = SKIP diff --git a/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt index 7a9b640a43..2c53c907c6 100644 --- a/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt +++ b/src/tests/deqp_support/deqp_khr_gles3_test_expectations.txt @@ -12,6 +12,8 @@ // Texture related failure on Pixel 4. 8616 VULKAN PIXEL4ORXL : KHR-GLES3.texture_lod_basic.lod_selection = FAIL +341780527 VULKAN PIXEL4ORXL : KHR-GLES3.clip_distance.coverage = FAIL + // Test bug - fails in ASAN 6678 VULKAN ANDROID : KHR-GLES3.packed_pixels.varied_rectangle.* = SKIP 6678 VULKAN NVIDIA : KHR-GLES3.packed_pixels.varied_rectangle.r8_snorm = SKIP @@ -20,6 +22,11 @@ 5976 LINUX VULKAN NVIDIA : KHR-GLES3.shaders.indexing.tmp_array.vertexid = FAIL +341780527 LINUX VULKAN NVIDIA : KHR-GLES3.clip_distance.coverage = FAIL +341780527 LINUX VULKAN NVIDIA : KHR-GLES3.cull_distance.functional = FAIL +341780527 WIN VULKAN NVIDIA : KHR-GLES3.clip_distance.coverage = FAIL +341780527 WIN VULKAN NVIDIA : KHR-GLES3.cull_distance.functional = FAIL + // Fails only with SwiftShader: // These only fail on Android @@ -59,6 +66,9 @@ 4019 SWIFTSHADER : KHR-GLES3.shaders.indexing.matrix_subscript.mat4_static_write_dynamic_read_vertex = FAIL 4019 SWIFTSHADER : KHR-GLES3.shaders.indexing.matrix_subscript.mat4_static_write_static_loop_read_fragment = FAIL 4019 SWIFTSHADER : KHR-GLES3.shaders.indexing.matrix_subscript.mat4_static_write_static_loop_read_vertex = FAIL +341780527 SWIFTSHADER : KHR-GLES3.clip_distance.coverage = FAIL +341780527 SWIFTSHADER : KHR-GLES3.clip_distance.functional = FAIL +341780527 SWIFTSHADER : KHR-GLES3.cull_distance.functional = FAIL // https://gitlab.khronos.org/opengl/API/-/issues/180 8048 VULKAN NVIDIA : KHR-GLES3.packed_pixels.pbo_rectangle.r8_snorm = SKIP @@ -83,6 +93,8 @@ // Samsung Galaxy S23 8157 GALAXYS23 VULKAN : KHR-GLES3.shaders.function.global_variable_aliasing_fragment = SKIP +341780527 GALAXYS23 VULKAN : KHR-GLES3.clip_distance.coverage = FAIL +341780527 GALAXYS23 VULKAN : KHR-GLES3.cull_distance.functional = FAIL // Snapdragon 8 Gen3 Mobile Reference Device b/328156792 PINEAPPLE VULKAN : KHR-GLES3.copy_tex_image_conversions.required.* = SKIP @@ -96,3 +108,6 @@ b/328156792 PINEAPPLE VULKAN : KHR-GLES3.shaders.function.global_variable_aliasi 8636 LINUX : KHR-GLES3.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit = FAIL 8636 WIN : KHR-GLES3.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit = FAIL b/332383430 PIXEL6 VULKAN : KHR-GLES3.texture_lod_bias.texture_lod_bias_all = FAIL + +// Flaky timeout +b/332383430 TSAN SWIFTSHADER : KHR-GLES3.texture_lod_bias.texture_lod_bias_all = SKIP diff --git a/src/tests/egl_tests/EGLDeviceTest.cpp b/src/tests/egl_tests/EGLDeviceTest.cpp index 8042aa9286..05c1834fe9 100644 --- a/src/tests/egl_tests/EGLDeviceTest.cpp +++ b/src/tests/egl_tests/EGLDeviceTest.cpp @@ -333,9 +333,6 @@ class EGLDeviceQueryTest : public ANGLETest<> void testSetUp() override { - const char *extensionString = - static_cast<const char *>(eglQueryString(getEGLWindow()->getDisplay(), EGL_EXTENSIONS)); - if (!eglQueryDeviceStringEXT) { FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceStringEXT was not " @@ -357,11 +354,13 @@ class EGLDeviceQueryTest : public ANGLETest<> EGLAttrib angleDevice = 0; EXPECT_EGL_TRUE( eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); - extensionString = static_cast<const char *>( - eglQueryDeviceStringEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_EXTENSIONS)); - if (strstr(extensionString, "EGL_ANGLE_device_d3d") == nullptr) + if (!IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d9") && + !IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d11")) { - FAIL() << "ANGLE extension EGL_ANGLE_device_d3d was not found"; + FAIL() << "ANGLE extensions EGL_ANGLE_device_d3d9 or EGL_ANGLE_device_d3d11 were not " + "found"; } } }; @@ -372,27 +371,29 @@ class EGLDeviceQueryTest : public ANGLETest<> // If the test is confitured to use D3D9, then it should succeed to obtain a D3D9 device. TEST_P(EGLDeviceQueryTest, QueryDevice) { - EGLAttrib device = 0; EGLAttrib angleDevice = 0; - if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + EXPECT_EGL_TRUE( + eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + + if (IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d11")) { - EXPECT_EGL_TRUE( - eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + EGLAttrib device11 = 0; EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), - EGL_D3D11_DEVICE_ANGLE, &device)); - ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device); + EGL_D3D11_DEVICE_ANGLE, &device11)); + ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device11); IDXGIDevice *dxgiDevice = DynamicCastComObject<IDXGIDevice>(d3d11Device); EXPECT_TRUE(dxgiDevice != nullptr); SafeRelease(dxgiDevice); } - if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + if (IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d9")) { - EXPECT_EGL_TRUE( - eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + EGLAttrib device9 = 0; EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), - EGL_D3D9_DEVICE_ANGLE, &device)); - IDirect3DDevice9 *d3d9Device = reinterpret_cast<IDirect3DDevice9 *>(device); + EGL_D3D9_DEVICE_ANGLE, &device9)); + IDirect3DDevice9 *d3d9Device = reinterpret_cast<IDirect3DDevice9 *>(device9); IDirect3D9 *d3d9 = nullptr; EXPECT_EQ(S_OK, d3d9Device->GetDirect3D(&d3d9)); EXPECT_TRUE(d3d9 != nullptr); @@ -406,22 +407,24 @@ TEST_P(EGLDeviceQueryTest, QueryDevice) // If the test is confitured to use D3D9, then it should fail to obtain a D3D9 device. TEST_P(EGLDeviceQueryTest, QueryDeviceBadAttribute) { - EGLAttrib device = 0; EGLAttrib angleDevice = 0; - if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + EXPECT_EGL_TRUE( + eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + + if (!IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d11")) { - EXPECT_EGL_TRUE( - eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + EGLAttrib device11 = 0; EXPECT_EGL_FALSE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), - EGL_D3D9_DEVICE_ANGLE, &device)); + EGL_D3D11_DEVICE_ANGLE, &device11)); } - if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + if (!IsEGLDeviceExtensionEnabled(reinterpret_cast<EGLDeviceEXT>(angleDevice), + "EGL_ANGLE_device_d3d9")) { - EXPECT_EGL_TRUE( - eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); + EGLAttrib device9 = 0; EXPECT_EGL_FALSE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), - EGL_D3D11_DEVICE_ANGLE, &device)); + EGL_D3D9_DEVICE_ANGLE, &device9)); } } diff --git a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp index d098f86535..e413cff0f3 100644 --- a/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp +++ b/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp @@ -1293,6 +1293,73 @@ TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurfaceWithTexBaseMaxLevelSe }); } +// Test that the following scenario works: +// - change IOSurface bound texture's max level to 0. +// - attach IOSurface bound texture to a FBO 1. +// - bind FBO 1 +// - clear FBO 1 -> this should trigger render targets initialization in backends. +// - bind FBO 0. +// - draw IOSurface bound texture to FBO 0. +// -> In the past, this could trigger the texture's render targets invalidation in metal backend. +// See https://issues.chromium.org/issues/335353385 +// - bind FBO 1 +// - blit FBO 0 to FBO 1. +// -> this will reconstruct render pass descriptor in metal backend. +// - flush to restart render encoder with new render pass descriptor. +// - draw. +TEST_P(IOSurfaceClientBufferTest, SetMaxLevelWouldInvalidateRenderTargetBug) +{ + ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt()); + ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); + + ANGLE_GL_PROGRAM(blueProgram, angle::essl1_shaders::vs::Simple(), + angle::essl1_shaders::fs::Blue()); + + ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4); + + GLTexture texture; + glBindTexture(getGLTextureTarget(), texture); + + // Bind the IOSurface to a texture. + EGLSurface pbuffer; + bindIOSurfaceToTexture(ioSurface, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, &pbuffer, &texture); + + // 1. Change the texture's max level to 0. + glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, 0); + EXPECT_GL_NO_ERROR(); + + // 2. Attach IOSurface bound texture to a FBO and clear it. + GLFramebuffer fbo; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getGLTextureTarget(), texture, 0); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // 3. Draw IOSurface bound texture to default FBO. + glBindFramebuffer(GL_FRAMEBUFFER, 0); + doSampleTestWithTexture(texture, R | G | B); + + // 3. Draw to custom FBO again + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glClear(GL_COLOR_BUFFER_BIT); + // Using a blit is important: it will trigger render pass reconstruction in + // metal backend due to DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 dirty bit. + glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glFlush(); // flush so that render encoder will be recreated again in metal backend. + glUseProgram(blueProgram); + drawQuad(blueProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); + glFlush(); + + // Expect the final color to be accumulated color + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + EXPECT_GL_NO_ERROR(); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(1, 2, 255, 255)); +} + // TODO(cwallez@chromium.org): Test setting width and height to less than the IOSurface's work as // expected. diff --git a/src/tests/egl_tests/EGLSyncTest.cpp b/src/tests/egl_tests/EGLSyncTest.cpp index 7a6d7d26ae..cf3b3aa623 100644 --- a/src/tests/egl_tests/EGLSyncTest.cpp +++ b/src/tests/egl_tests/EGLSyncTest.cpp @@ -708,4 +708,16 @@ void main(void) EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); } +// Test that leaked fences are cleaned up in a safe way. Regression test for sync objects using tail +// calls for destruction. +TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction) +{ + ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension()); + + EGLDisplay display = getEGLWindow()->getDisplay(); + + EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr); + EXPECT_NE(sync, EGL_NO_SYNC_KHR); +} + ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLSyncTest); diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp index 58feeaf77b..43a58852c0 100644 --- a/src/tests/gl_tests/GLSLTest.cpp +++ b/src/tests/gl_tests/GLSLTest.cpp @@ -3512,6 +3512,26 @@ TEST_P(GLSLTest_ES3, InitGlobalArrayWithArrayIndexing) EXPECT_NE(0u, program); } +// Test that constant global matrix array with an initializer compiles. +TEST_P(GLSLTest_ES3, InitConstantMatrixArray) +{ + constexpr char kFS[] = R"(#version 300 es + precision highp float; + uniform int index; + + const mat4 matrix = mat4(1.0); + const mat4 array[1] = mat4[1](matrix); + out vec4 my_FragColor; + void main() { + my_FragColor = vec4(array[index][1].rgb, 1.0); + })"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); +} + // Test that index-constant sampler array indexing is supported. TEST_P(GLSLTest, IndexConstantSamplerArrayIndexing) { @@ -19231,6 +19251,52 @@ Foo foo(float bar) EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); } +// Test that double underscores user defined name is allowed +TEST_P(GLSLTest_ES3, DoubleUnderscoresName) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 oColor; +uniform struct __Data {float red;} data; +void main() {oColor=vec4(data.red,0,1,1);})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + // populate uniform + GLint uniformLocation = glGetUniformLocation(program, "data.red"); + EXPECT_NE(uniformLocation, -1); + glUniform1f(uniformLocation, 0); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + +// Test that user defined name starts with "ANGLE" or "ANGLE_" +TEST_P(GLSLTest_ES3, VariableNameStartsWithANGLE) +{ + constexpr char kFS[] = R"(#version 300 es +precision mediump float; +out vec4 oColor; +uniform struct ANGLEData{float red;} data; +uniform struct ANGLE_Data{float green;} _data; +void main() {oColor=vec4(data.red,_data.green,1,1);})"; + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + glUseProgram(program); + // populate uniform + GLint uniformRedLocation = glGetUniformLocation(program, "data.red"); + GLint uniformGreenLocation = glGetUniformLocation(program, "_data.green"); + EXPECT_NE(uniformRedLocation, -1); + EXPECT_NE(uniformGreenLocation, -1); + glUniform1f(uniformRedLocation, 0); + glUniform1f(uniformGreenLocation, 0); + + drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f); + EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); + ASSERT_GL_NO_ERROR(); +} + // Test that underscores in array names work with out arrays. TEST_P(GLSLTest_ES3, UnderscoresWorkWithOutArrays) { diff --git a/src/tests/gl_tests/MultithreadingTest.cpp b/src/tests/gl_tests/MultithreadingTest.cpp index 869cb191f7..25711061ee 100644 --- a/src/tests/gl_tests/MultithreadingTest.cpp +++ b/src/tests/gl_tests/MultithreadingTest.cpp @@ -3847,6 +3847,254 @@ TEST_P(MultithreadingTest, ProgramLinkAndBind) ASSERT_NE(currentStep, Step::Abort); } +// Test that two contexts in share group can generate, delete and bind buffers for themselves in +// parallel. +TEST_P(MultithreadingTestES3, SimultaneousBufferBindAndGen) +{ + ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading()); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; + +layout(std140) uniform Block +{ + vec4 colorIn; +}; + +out vec4 color; + +void main() +{ + color = colorIn; +})"; + + constexpr int kSurfaceWidth = 32; + constexpr int kSurfaceHeight = 128; + + // Sync primitives + std::mutex mutex; + std::condition_variable condVar; + + enum class Step + { + Start, + Thread0Ready, + Thread1Ready, + Finish, + Abort, + }; + Step currentStep = Step::Start; + + auto threadFunc = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context, uint32_t index) { + ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar); + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context)); + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + // Make sure the two threads start work around the same time + if (index == 0) + { + threadSynchronization.nextStep(Step::Thread0Ready); + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1Ready)); + } + else + { + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0Ready)); + threadSynchronization.nextStep(Step::Thread1Ready); + } + + std::vector<GLuint> buffers(kSurfaceWidth * kSurfaceHeight); + + glEnable(GL_SCISSOR_TEST); + for (int y = 0; y < kSurfaceHeight; ++y) + { + for (int x = 0; x < kSurfaceWidth; ++x) + { + GLuint &buffer = buffers[y * kSurfaceWidth + x]; + const float bufferData[4] = { + ((y * kSurfaceWidth + x + index * 100) % 255) / 255.0f, + ((y * kSurfaceWidth + x + index * 100 + 1) % 255) / 255.0f, + ((y * kSurfaceWidth + x + index * 100 + 2) % 255) / 255.0f, + ((y * kSurfaceWidth + x + index * 100 + 3) % 255) / 255.0f, + }; + + // Generate one buffer per pixel and shade the pixel with it. + glGenBuffers(1, &buffer); + glBindBuffer(GL_UNIFORM_BUFFER, buffers[y * kSurfaceWidth + x]); + glBufferData(GL_UNIFORM_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer); + + glScissor(x, y, 1, 1); + drawQuad(program, essl3_shaders::PositionAttrib(), 0); + + if ((x + y) % 2 == 0) + { + glDeleteBuffers(1, &buffer); + buffer = 0; + } + } + } + + // Verify the results + auto verify = [&](int x, int y) { + const GLColor expect((y * kSurfaceWidth + x + index * 100) % 255, + (y * kSurfaceWidth + x + index * 100 + 1) % 255, + (y * kSurfaceWidth + x + index * 100 + 2) % 255, + (y * kSurfaceWidth + x + index * 100 + 3) % 255); + EXPECT_PIXEL_COLOR_EQ(x, y, expect); + }; + + verify(0, 0); + verify(0, kSurfaceHeight - 1); + verify(kSurfaceWidth - 1, 0); + verify(kSurfaceWidth - 1, kSurfaceHeight - 1); + verify(kSurfaceWidth / 2, kSurfaceHeight / 2); + ASSERT_GL_NO_ERROR(); + + if (index == 0) + { + threadSynchronization.nextStep(Step::Finish); + } + else + { + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); + } + }; + + auto thread0 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) { + threadFunc(dpy, surface, context, 0); + }; + auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) { + threadFunc(dpy, surface, context, 1); + }; + + std::array<LockStepThreadFunc, 2> threadFuncs = { + std::move(thread0), + std::move(thread1), + }; + + RunLockStepThreadsWithSize(getEGLWindow(), kSurfaceWidth, kSurfaceHeight, threadFuncs.size(), + threadFuncs.data()); + + ASSERT_NE(currentStep, Step::Abort); +} + +// Test that ref counting is thread-safe when the same buffer is used in multiple threads. +TEST_P(MultithreadingTestES3, SimultaneousBufferBind) +{ + ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading()); + + constexpr char kFS[] = R"(#version 300 es +precision mediump float; + +layout(std140) uniform Block +{ + vec4 colorIn; +}; + +out vec4 color; + +void main() +{ + color = colorIn; +})"; + + constexpr int kSurfaceWidth = 32; + constexpr int kSurfaceHeight = 128; + + GLuint buffer; + GLsync sync = nullptr; + + // Sync primitives + std::mutex mutex; + std::condition_variable condVar; + + enum class Step + { + Start, + Thread0Ready, + Thread1Ready, + Finish, + Abort, + }; + Step currentStep = Step::Start; + + auto thread0 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) { + ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar); + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context)); + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + // Create the buffer in this context + glGenBuffers(1, &buffer); + + constexpr float kBufferData[4] = { + 10.0f / 255.0f, + 50.0f / 255.0f, + 130.0f / 255.0f, + 220.0f / 255.0f, + }; + glBindBuffer(GL_UNIFORM_BUFFER, buffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW); + + sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + + // Make sure the two threads start work around the same time + threadSynchronization.nextStep(Step::Thread0Ready); + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1Ready)); + + // Bind and unbind the buffer many times. If ref counting is not thread safe, chances are + // the ref count would be incorrect in the end. This can result in the buffer prematurely + // getting deleted. + for (uint32_t i = 0; i < 8000; ++i) + { + glBindBuffer(GL_UNIFORM_BUFFER, i % 2 == 0 ? 0 : buffer); + } + ASSERT_GL_NO_ERROR(); + + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish)); + }; + auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) { + ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar); + EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context)); + + ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS); + + ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0Ready)); + threadSynchronization.nextStep(Step::Thread1Ready); + + glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + + // Bind and unbind the buffer many times. + for (uint32_t i = 0; i < 4000; ++i) + { + glBindBuffer(GL_UNIFORM_BUFFER, i % 2 == 0 ? buffer : 0); + } + + // Draw with it to make sure buffer is still valid and not accidentally deleted due to bad + // ref counting. + glBindBuffer(GL_UNIFORM_BUFFER, buffer); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer); + drawQuad(program, essl3_shaders::PositionAttrib(), 0); + + // Verify the results + const GLColor expect(10, 50, 130, 220); + EXPECT_PIXEL_RECT_EQ(0, 0, kSurfaceWidth, kSurfaceHeight, expect); + ASSERT_GL_NO_ERROR(); + + threadSynchronization.nextStep(Step::Finish); + }; + + std::array<LockStepThreadFunc, 2> threadFuncs = { + std::move(thread0), + std::move(thread1), + }; + + RunLockStepThreadsWithSize(getEGLWindow(), kSurfaceWidth, kSurfaceHeight, threadFuncs.size(), + threadFuncs.data()); + + ASSERT_NE(currentStep, Step::Abort); +} ANGLE_INSTANTIATE_TEST( MultithreadingTest, ES2_OPENGL(), diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp index f38a0f99f4..1a1922bc53 100644 --- a/src/tests/gl_tests/RobustResourceInitTest.cpp +++ b/src/tests/gl_tests/RobustResourceInitTest.cpp @@ -2235,25 +2235,6 @@ TEST_P(RobustResourceInitTestES31, Multisample2DTextureArray) } } -// Tests that using an out of bounds draw offset with a dynamic array succeeds. -TEST_P(RobustResourceInitTest, DynamicVertexArrayOffsetOutOfBounds) -{ - ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); - glUseProgram(program); - - GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib()); - ASSERT_NE(-1, posLoc); - - glEnableVertexAttribArray(posLoc); - GLBuffer buf; - glBindBuffer(GL_ARRAY_BUFFER, buf); - glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500)); - glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW); - glDrawArrays(GL_TRIANGLES, 0, 3); - - // Either no error or invalid operation is okay. -} - // Test to cover a bug that the multisampled depth attachment of a framebuffer are not successfully // initialized before it is used as the read framebuffer in blitFramebuffer. // Referenced from the following WebGL CTS: diff --git a/src/tests/gl_tests/ShaderAlgorithmTest.cpp b/src/tests/gl_tests/ShaderAlgorithmTest.cpp index e2a5ca0d3b..4ec785c7cb 100644 --- a/src/tests/gl_tests/ShaderAlgorithmTest.cpp +++ b/src/tests/gl_tests/ShaderAlgorithmTest.cpp @@ -118,7 +118,7 @@ TEST_P(ShaderAlgorithmTest, rgb_to_hsl_vertex_shader) ASSERT_GL_NO_ERROR(); - float maxVal = std::max(sx, std::max(sy, 0.33f * sx + 0.5f * sy)); + float maxVal = std::max({sx, sy, 0.33f * sx + 0.5f * sy}); if (abs(maxVal - sx) <= epsilon) { EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp index ed0e19fa00..4881115c8c 100644 --- a/src/tests/gl_tests/StateChangeTest.cpp +++ b/src/tests/gl_tests/StateChangeTest.cpp @@ -8056,22 +8056,6 @@ TEST_P(SimpleStateChangeTestES3, InvalidateFramebufferShouldntInvalidateReadFram EXPECT_GL_NO_ERROR(); } -// Covers situations where vertex conversion could read out of bounds. -TEST_P(SimpleStateChangeTestES3, OutOfBoundsByteAttribute) -{ - ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); - glUseProgram(testProgram); - - GLBuffer buffer; - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, 2, nullptr, GL_STREAM_COPY); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_BYTE, false, 0xff, reinterpret_cast<const void *>(0xfe)); - - glDrawArraysInstanced(GL_TRIANGLE_STRIP, 1, 10, 1000); -} - // Test that respecifies a buffer after we start XFB. TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback) { diff --git a/src/tests/gl_tests/VertexAttributeTest.cpp b/src/tests/gl_tests/VertexAttributeTest.cpp index a1572e05d0..1b1d6c4555 100644 --- a/src/tests/gl_tests/VertexAttributeTest.cpp +++ b/src/tests/gl_tests/VertexAttributeTest.cpp @@ -4507,43 +4507,6 @@ void main() EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green); } -// Test that vertex conversion correctly no-ops when the vertex format requires conversion but there -// are no vertices to convert. -TEST_P(VertexAttributeTest, ConversionWithNoVertices) -{ - constexpr char kVS[] = R"(precision highp float; -attribute vec3 attr1; -void main(void) { - gl_Position = vec4(attr1, 1.0); -})"; - - constexpr char kFS[] = R"(precision highp float; -void main(void) { - gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); -})"; - - GLBuffer buffer; - glBindBuffer(GL_ARRAY_BUFFER, buffer); - std::array<int8_t, 12> data = { - 1, - }; - glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW); - - ANGLE_GL_PROGRAM(program, kVS, kFS); - glBindAttribLocation(program, 0, "attr1"); - glLinkProgram(program); - ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true)); - glUseProgram(program); - - // Set the offset the athe attribute past the end of the buffer but use a format that requires - // conversion in Vulkan - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_BYTE, true, 128, reinterpret_cast<void *>(256)); - - glDrawArrays(GL_TRIANGLES, 0, 3); - EXPECT_GL_NO_ERROR(); -} - // Test that pipeline is recreated properly when switching from ARRAY buffer to client buffer, // while removing client buffer. Bug observed in Dragonmania game. TEST_P(VertexAttributeTestES31, ArrayToClientBufferStride) diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp index 028e11767d..4062cf844c 100644 --- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp +++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp @@ -6365,6 +6365,78 @@ void main() { } } +// Test that vertex conversion correctly no-ops when the vertex format requires conversion but there +// are no vertices to convert. +TEST_P(WebGLCompatibilityTest, ConversionWithNoVertices) +{ + constexpr char kVS[] = R"(precision highp float; +attribute vec3 attr1; +void main(void) { + gl_Position = vec4(attr1, 1.0); +})"; + + constexpr char kFS[] = R"(precision highp float; +void main(void) { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); +})"; + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + std::array<int8_t, 12> data = { + 1, + }; + glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW); + + ANGLE_GL_PROGRAM(program, kVS, kFS); + glBindAttribLocation(program, 0, "attr1"); + glLinkProgram(program); + ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true)); + glUseProgram(program); + + // Set the offset of the attribute past the end of the buffer but use a format that requires + // conversion in Vulkan + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_BYTE, true, 128, reinterpret_cast<void *>(256)); + + glDrawArrays(GL_TRIANGLES, 0, 3); + // Either no error or invalid operation is okay. +} + +// Tests that using an out of bounds draw offset with a dynamic array succeeds. +TEST_P(WebGLCompatibilityTest, DynamicVertexArrayOffsetOutOfBounds) +{ + ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); + glUseProgram(program); + + GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib()); + ASSERT_NE(-1, posLoc); + + glEnableVertexAttribArray(posLoc); + GLBuffer buf; + glBindBuffer(GL_ARRAY_BUFFER, buf); + glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const void *>(500)); + glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_DYNAMIC_DRAW); + glDrawArrays(GL_TRIANGLES, 0, 3); + + // Either no error or invalid operation is okay. +} + +// Covers situations where vertex conversion could read out of bounds. +TEST_P(WebGL2CompatibilityTest, OutOfBoundsByteAttribute) +{ + ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); + glUseProgram(testProgram); + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, 2, nullptr, GL_STREAM_COPY); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_BYTE, false, 0xff, reinterpret_cast<const void *>(0xfe)); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 1, 10, 1000); +} + // Test for a mishandling of instanced vertex attributes with zero-sized buffers bound on Apple // OpenGL drivers. TEST_P(WebGL2CompatibilityTest, DrawWithZeroSizedBuffer) diff --git a/src/tests/perf_tests/TracePerfTest.cpp b/src/tests/perf_tests/TracePerfTest.cpp index ccc98b9792..567f92e49c 100644 --- a/src/tests/perf_tests/TracePerfTest.cpp +++ b/src/tests/perf_tests/TracePerfTest.cpp @@ -848,9 +848,9 @@ TracePerfTest::TracePerfTest(std::unique_ptr<const TracePerfParams> params) mStartFrame(0), mEndFrame(0) { - bool isAMD = IsAMD() && !mParams->isSwiftshader(); - bool isAMDLinux = isAMD && IsLinux(); - // bool isAMDLinuxANGLE = isAMDLinux && mParams->isANGLE(); + bool isAMD = IsAMD() && !mParams->isSwiftshader(); + bool isAMDLinux = isAMD && IsLinux(); + bool isAMDLinuxANGLE = isAMDLinux && mParams->isANGLE(); bool isAMDLinuxNative = isAMDLinux && !mParams->isANGLE(); bool isAMDWin = isAMD && IsWindows(); bool isAMDWinANGLE = isAMDWin && mParams->isANGLE(); @@ -1497,6 +1497,10 @@ TracePerfTest::TracePerfTest(std::unique_ptr<const TracePerfParams> params) if (traceNameIs("antutu_refinery")) { + if (isIntelLinuxANGLE || isAMDLinuxANGLE) + { + skipTest("https://anglebug.com/342545097 fails on Mesa 23.2.1"); + } addExtensionPrerequisite("GL_ANDROID_extension_pack_es31a"); } diff --git a/testing b/testing -Subproject a2a6e48c98e5e5869e822b542e935514d843c43 +Subproject 940cfd4db1dfb7712cb94d68f19e476f6ed6e3a diff --git a/third_party/SwiftShader b/third_party/SwiftShader -Subproject da334852e70510d259bfa8cbaa7c5412966b2f4 +Subproject 90519141a709a92db90640b52176aaf82942e93 diff --git a/third_party/VK-GL-CTS/src b/third_party/VK-GL-CTS/src -Subproject 9d7b4c3d553331e316321942e2eb8413e4081c7 +Subproject fd5cc7b1e07578e8e807696034ab894b134f428 diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp -Subproject 31bdf8fec41f04dfe86976734cbad22ded4ca1f +Subproject b027bd3c0b3ce035c8da06a78e7ab8db2d5c444 diff --git a/third_party/android_deps b/third_party/android_deps -Subproject 36a6c64282adbe58f343d9c0cbdf45d0e6402db +Subproject 2888a739e9b8b8514807a5a0d8b26f91a7e4e91 diff --git a/third_party/catapult b/third_party/catapult -Subproject 47d3198a953f28d06b46bb6f9293b4e0b384d15 +Subproject ec40c25bd83f043ebc76fb368414016b0515675 diff --git a/third_party/clspv/BUILD.gn b/third_party/clspv/BUILD.gn index 90770466c5..8b266473d3 100644 --- a/third_party/clspv/BUILD.gn +++ b/third_party/clspv/BUILD.gn @@ -222,7 +222,7 @@ source_set("clspv_passes") { ":clspv_reflection", "gn/llvm/config:llvm-config", "gn/llvm/sources:clspv_llvm_components", - "//third_party/vulkan-deps/spirv-headers/src:spv_headers", + "//third_party/spirv-headers/src:spv_headers", ] configs += [ @@ -359,7 +359,7 @@ executable("clspv-reflection") { ":clspv_core", ":clspv_reflection", "${spirv_tools_dir}:spvtools_link", - "//third_party/vulkan-deps/spirv-headers/src:spv_headers", + "//third_party/spirv-headers/src:spv_headers", ] include_dirs = [ diff --git a/third_party/dawn b/third_party/dawn -Subproject 5406e9dfbe0ba766e5a7571e1ad7c2dc48ad57e +Subproject d32858a3045a89e8c5ff919107ee76c8b103afd diff --git a/third_party/depot_tools b/third_party/depot_tools -Subproject df437783c243fef294e6af2e44de383e751a376 +Subproject 09c232e7c0d5670695d1f8f70d05ed1a215e438 diff --git a/third_party/flatbuffers/DIR_METADATA b/third_party/flatbuffers/DIR_METADATA index 637eb4dc77..f34553f340 100644 --- a/third_party/flatbuffers/DIR_METADATA +++ b/third_party/flatbuffers/DIR_METADATA @@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Platform>Extensions>API" } +buganizer_public: { + component_id: 1456781 +} diff --git a/third_party/flatbuffers/README.chromium b/third_party/flatbuffers/README.chromium index b45064f841..47669af672 100644 --- a/third_party/flatbuffers/README.chromium +++ b/third_party/flatbuffers/README.chromium @@ -1,8 +1,8 @@ Name: FlatBuffers Short Name: flatbuffers URL: https://github.com/google/flatbuffers -Version: bcb9ef187628fe07514e57756d05e6a6296f7dc5 -Date: 2023-10-03 +Version: c696275eaffec33796b5ca8755614fd9fec0a6a7 +Date: 2024-05-09 License: Apache 2.0 License File: LICENSE Security Critical: yes diff --git a/third_party/flatbuffers/generated/tests/alignment_test_generated.h b/third_party/flatbuffers/generated/tests/alignment_test_generated.h index a23479e2c6..e123300e28 100644 --- a/third_party/flatbuffers/generated/tests/alignment_test_generated.h +++ b/third_party/flatbuffers/generated/tests/alignment_test_generated.h @@ -7,8 +7,8 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && FLATBUFFERS_VERSION_MINOR == 5 && - FLATBUFFERS_VERSION_REVISION == 26, +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && FLATBUFFERS_VERSION_MINOR == 3 && + FLATBUFFERS_VERSION_REVISION == 25, "Non-compatible flatbuffers version included"); struct BadAlignmentSmall; diff --git a/third_party/flatbuffers/generated/tests/arrays_test_generated.h b/third_party/flatbuffers/generated/tests/arrays_test_generated.h index 45e5f2475a..f2264df536 100644 --- a/third_party/flatbuffers/generated/tests/arrays_test_generated.h +++ b/third_party/flatbuffers/generated/tests/arrays_test_generated.h @@ -7,8 +7,8 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && FLATBUFFERS_VERSION_MINOR == 5 && - FLATBUFFERS_VERSION_REVISION == 26, +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && FLATBUFFERS_VERSION_MINOR == 3 && + FLATBUFFERS_VERSION_REVISION == 25, "Non-compatible flatbuffers version included"); namespace MyGame diff --git a/third_party/flatbuffers/src b/third_party/flatbuffers/src -Subproject bcb9ef187628fe07514e57756d05e6a6296f7dc +Subproject 150644d7f4d030a0629c564fd90dc3becab7763 diff --git a/third_party/glslang/DIR_METADATA b/third_party/glslang/DIR_METADATA new file mode 100644 index 0000000000..348e5424b5 --- /dev/null +++ b/third_party/glslang/DIR_METADATA @@ -0,0 +1,4 @@ +monorail { + component: "Internals>GPU>Internals" +} +team_email: "graphics-dev@chromium.org" diff --git a/third_party/glslang/LICENSE b/third_party/glslang/LICENSE new file mode 100644 index 0000000000..8b2e82136b --- /dev/null +++ b/third_party/glslang/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2015-2016 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT + https://www.khronos.org/registry/ + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. diff --git a/third_party/glslang/README.chromium b/third_party/glslang/README.chromium new file mode 100644 index 0000000000..7c3e05ab69 --- /dev/null +++ b/third_party/glslang/README.chromium @@ -0,0 +1,16 @@ +Name: Khronos reference front-end for GLSL and ESSL +Short Name: glslang +URL: https://github.com/KhronosGroup/glslang +Version: Unknown +Security Critical: yes +Shipped: no +License: MIT +License File: LICENSE + +Description: +An OpenGL and OpenGL ES shader front end and validator. + +Local Modifications: +Added OWNERS, README.chromium. +Ported build rules from CMake to GN. +5/13/2016 - Updated GN build rules to include new files added in repository. diff --git a/third_party/glslang/src b/third_party/glslang/src new file mode 160000 +Subproject 7c3c50ea94354d06dc8c280de8b8a5d5aacbbb1 diff --git a/third_party/libc++/src b/third_party/libc++/src -Subproject e3b94d0e5b86883fd77696bf10dc33ba250ba99 +Subproject 852bc6746f45add53fec19f3a29280e69e358d4 diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src -Subproject d17298ab09b44bbc95e5e59c0f285145d0e5f8a +Subproject ba370858669b1e905db5ded82c8887095b61dc1 diff --git a/third_party/libunwind/src b/third_party/libunwind/src -Subproject 419b03c0b8f20d6da9ddcb0d661a94a97cdd7da +Subproject e0a4f3561e7f7ce10573917b60c7027e3b599e6 diff --git a/third_party/spirv-cross/DIR_METADATA b/third_party/spirv-cross/DIR_METADATA new file mode 100644 index 0000000000..e353adfc5e --- /dev/null +++ b/third_party/spirv-cross/DIR_METADATA @@ -0,0 +1,4 @@ +monorail: { + component: "Internals>GPU>Internals" +} +team_email: "graphics-dev@chromium.org" diff --git a/third_party/spirv-cross/README.chromium b/third_party/spirv-cross/README.chromium new file mode 100644 index 0000000000..42c1f1502a --- /dev/null +++ b/third_party/spirv-cross/README.chromium @@ -0,0 +1,13 @@ +Name: SPIRV-Cross +Short Name: SPIRV-Cross +URL: https://github.com/KhronosGroup/SPIRV-Cross +Version: Unknown +Security Critical: yes +Shipped: no +License: Apache 2.0 +License File: src/LICENSE + +Description: +A translator from SPIR-V bytecode to other shading languages like GLSL, HLSL +and MSL. This project is not secure (yet!) and should only be used for +prototyping, and not shipped to users. diff --git a/third_party/spirv-cross/src b/third_party/spirv-cross/src new file mode 160000 +Subproject b8fcf307f1f347089e3c46eb4451d27f32ebc8d diff --git a/third_party/spirv-headers/DIR_METADATA b/third_party/spirv-headers/DIR_METADATA new file mode 100644 index 0000000000..e353adfc5e --- /dev/null +++ b/third_party/spirv-headers/DIR_METADATA @@ -0,0 +1,4 @@ +monorail: { + component: "Internals>GPU>Internals" +} +team_email: "graphics-dev@chromium.org" diff --git a/third_party/spirv-headers/LICENSE b/third_party/spirv-headers/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/third_party/spirv-headers/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/third_party/spirv-headers/README.chromium b/third_party/spirv-headers/README.chromium new file mode 100644 index 0000000000..758a714920 --- /dev/null +++ b/third_party/spirv-headers/README.chromium @@ -0,0 +1,15 @@ +Name: SPIR-V Headers +Short Name: spirv-headers +URL: https://github.com/KhronosGroup/SPIRV-Headers.git +Version: unknown +Security Critical: yes +Shipped: yes +License: MIT +License File: LICENSE + +Description: +This repository contains machine-readable files from the SPIR-V Registry. This includes: + +* Header files for various languages. +* JSON files describing the grammar for the SPIR-V core instruction set, and for the GLSL.std.450 extended instruction set. +* The XML registry file. diff --git a/third_party/spirv-headers/src b/third_party/spirv-headers/src new file mode 160000 +Subproject 49a1fceb9b1d087f3c25ad5ec077bb0e4623129 diff --git a/third_party/spirv-tools/DIR_METADATA b/third_party/spirv-tools/DIR_METADATA new file mode 100644 index 0000000000..376e2293f3 --- /dev/null +++ b/third_party/spirv-tools/DIR_METADATA @@ -0,0 +1,5 @@ +monorail { + component: "Internals>GPU>Internals" +} + +team_email: "graphics-dev@chromium.org" diff --git a/third_party/spirv-tools/LICENSE b/third_party/spirv-tools/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/third_party/spirv-tools/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/third_party/spirv-tools/README.chromium b/third_party/spirv-tools/README.chromium new file mode 100644 index 0000000000..a2d18d7e4d --- /dev/null +++ b/third_party/spirv-tools/README.chromium @@ -0,0 +1,16 @@ +Name: SPIR-V Tools +Short Name: SPIRV-Tools +URL: https://github.com/KhronosGroup/SPIRV-Tools.git +Version: Unknown +Security Critical: yes +Shipped: yes +License: Apache 2.0 +License File: LICENSE + +Description: +The SPIR-V Tools project provides an API and commands for processing +SPIR-V modules. + +Local Modifications: +Added OWNERS, README.chromium. +Ported build rules from CMake to GN. diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src new file mode 160000 +Subproject 77c40bece1b8b441eee432fc9d74efbf985f777 diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps -Subproject 643408ea2a0685352d831a97601997c9ea246f6 +Subproject feb3ce48e50956465d171e37c548bb8e44a30ef diff --git a/third_party/vulkan-headers/DIR_METADATA b/third_party/vulkan-headers/DIR_METADATA new file mode 100644 index 0000000000..e353adfc5e --- /dev/null +++ b/third_party/vulkan-headers/DIR_METADATA @@ -0,0 +1,4 @@ +monorail: { + component: "Internals>GPU>Internals" +} +team_email: "graphics-dev@chromium.org" diff --git a/third_party/vulkan-headers/LICENSE.txt b/third_party/vulkan-headers/LICENSE.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/third_party/vulkan-headers/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/third_party/vulkan-headers/README.chromium b/third_party/vulkan-headers/README.chromium new file mode 100644 index 0000000000..947684c776 --- /dev/null +++ b/third_party/vulkan-headers/README.chromium @@ -0,0 +1,12 @@ +Name: Vulkan API headers +Short Name: Vulkan +URL: https://github.com/KhronosGroup/Vulkan-Headers +Version: 1.2.140 +Revision: 9250d5ae8f50202005233dc0512a1d460c8b4833 +Security Critical: yes +Shipped: yes +License: Apache 2.0 +License File: LICENSE.txt + +Description: +Vulkan Header files and API registry diff --git a/third_party/vulkan-headers/src b/third_party/vulkan-headers/src new file mode 160000 +Subproject 5677bafb820e476441e9e1f745371b72133407d diff --git a/third_party/vulkan-loader/README.chromium b/third_party/vulkan-loader/README.chromium new file mode 100644 index 0000000000..654ff3b446 --- /dev/null +++ b/third_party/vulkan-loader/README.chromium @@ -0,0 +1,16 @@ +Name: Vulkan Loader Components +Short Name: Vulkan Loader +Version: N/A +URL: https://github.com/KhronosGroup/Vulkan-Loader +SOURCE CODE: git clone https://github.com/KhronosGroup/Vulkan-Loader.git +Revision: HEAD +Security Critical: no +Shipped: yes +License: Apache 2.0 +License File: src/LICENSE.txt + +Description: +The Vulkan Loader Components are used to build the open-source desktop Vulkan loader. The loader +is a library that loads the Vulkan entry points and hooks them into the correct layers and the +client driver (ICD). This is required for using Vulkan layers and applications. + diff --git a/third_party/vulkan-loader/src b/third_party/vulkan-loader/src new file mode 160000 +Subproject d3d530c90dd6549bcfc7cfaedd3ff85fe8ff04a diff --git a/third_party/vulkan-tools/README.chromium b/third_party/vulkan-tools/README.chromium new file mode 100644 index 0000000000..ccf51ffcde --- /dev/null +++ b/third_party/vulkan-tools/README.chromium @@ -0,0 +1,15 @@ +Name: Khronos Vulkan Tools Components +Short Name: Vulkan Tools +Version: N/A +URL: https://github.com/KhronosGroup/Vulkan-Tools +SOURCE CODE: git clone https://github.com/KhronosGroup/Vulkan-Tools.git +Revision: HEAD +Security Critical: no +Shipped: no +License: Apache 2.0 +License File: src/LICENSE.txt + +Description: +The Khronos Vulkan Tools Components contain the Vulkan Mock Installable +Client Driver (ICD) as well as the vulkaninfo utility. + diff --git a/third_party/vulkan-tools/src b/third_party/vulkan-tools/src new file mode 160000 +Subproject d67a9d3a394e11c1c4c0f480124f5b7925cb1b4 diff --git a/third_party/vulkan-utility-libraries/README.chromium b/third_party/vulkan-utility-libraries/README.chromium new file mode 100644 index 0000000000..64528cbc03 --- /dev/null +++ b/third_party/vulkan-utility-libraries/README.chromium @@ -0,0 +1,15 @@ +Name: Khronos Vulkan Utility Libraries +Short Name: Vulkan Utility Libraries +Version: N/A +URL: https://github.com/KhronosGroup/Vulkan-Utility-Libraries +SOURCE CODE: git clone https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git +Revision: HEAD +Security Critical: no +Shipped: no +License: Apache 2.0 +License File: src/LICENSE.md + +Description: + +The Khronos Vulkan Utility Libraries contains the layer settings library and +miscellaneous utility headers for Vulkan developers. diff --git a/third_party/vulkan-utility-libraries/src b/third_party/vulkan-utility-libraries/src new file mode 160000 +Subproject f6c54531066c6d28ef403b50ff9cff3ea195d28 diff --git a/third_party/vulkan-validation-layers/README.chromium b/third_party/vulkan-validation-layers/README.chromium new file mode 100644 index 0000000000..1c5714b315 --- /dev/null +++ b/third_party/vulkan-validation-layers/README.chromium @@ -0,0 +1,18 @@ +Name: Khronos Vulkan Validation Layers Components +Short Name: Vulkan Validation Layers +Version: N/A +URL: https://github.com/KhronosGroup/Vulkan-ValidationLayers +SOURCE CODE: git clone https://github.com/KhronosGroup/Vulkan-ValidationLayers.git +Revision: HEAD +Security Critical: no +Shipped: no +License: Apache 2.0 +License File: src/LICENSE.txt + +Description: +The Khronos Vulkan Validation Layers Components consist of the Vulkan +Validation Layers. The layers help validate Vulkan programs at runtime +for development. When enabled the Vulkan loader will hook the layers +into the Vulkan APIs so that they evaluate Vulkan API calls and flag +the incorrect use of the API with callbacks. The layers are essential +for developing Vulkan applications. diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src new file mode 160000 +Subproject b25dea41d4a441268745ed9a83f82757170ec45 diff --git a/third_party/zlib b/third_party/zlib -Subproject 7d77fb7fd66d8a5640618ad32c71fdeb7d3e02d +Subproject 209717dd69cd62f24cbacc4758261ae2dd78cfa diff --git a/tools/android b/tools/android -Subproject cc51a5ea8611565ff48db1a11c08e90d03484bd +Subproject 34192533e15dd37bd3c91910247fb925d1e1532 diff --git a/tools/clang b/tools/clang -Subproject 964cf5c799c2284d52a88b1a516481852e7a216 +Subproject 9772a0a3490ed8f5977babbb01182944b44d3ea diff --git a/tools/mb b/tools/mb -Subproject 54a120d570f317c69bb155481629e2121df7554 +Subproject 973c25352084d231639ecd6f110e8343e203def diff --git a/tools/perf b/tools/perf -Subproject 7ef4ff5ba36be22f641d0f08f34402f85db1849 +Subproject ce2f1c1daa5716c697105213772e13be838ee44 diff --git a/util/android/third_party/android_native_app_glue.c b/util/android/third_party/android_native_app_glue.c index ad9c55816e..934e2f2b2a 100644 --- a/util/android/third_party/android_native_app_glue.c +++ b/util/android/third_party/android_native_app_glue.c @@ -12,18 +12,17 @@ * 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 "android_native_app_glue.h" + #include <jni.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <sys/resource.h> -#include "android_native_app_glue.h" #include <android/log.h> #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) @@ -48,17 +47,12 @@ static void free_saved_state(struct android_app* android_app) { int8_t android_app_read_cmd(struct android_app* android_app) { int8_t cmd; - if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { - switch (cmd) { - case APP_CMD_SAVE_STATE: - free_saved_state(android_app); - break; - } - return cmd; - } else { + if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) { LOGE("No data on command pipe!"); + return -1; } - return -1; + if (cmd == APP_CMD_SAVE_STATE) free_saved_state(android_app); + return cmd; } static void print_cur_config(struct android_app* android_app) { @@ -89,7 +83,7 @@ static void print_cur_config(struct android_app* android_app) { void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { switch (cmd) { case APP_CMD_INPUT_CHANGED: - LOGV("APP_CMD_INPUT_CHANGED\n"); + LOGV("APP_CMD_INPUT_CHANGED"); pthread_mutex_lock(&android_app->mutex); if (android_app->inputQueue != NULL) { AInputQueue_detachLooper(android_app->inputQueue); @@ -106,7 +100,7 @@ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { break; case APP_CMD_INIT_WINDOW: - LOGV("APP_CMD_INIT_WINDOW\n"); + LOGV("APP_CMD_INIT_WINDOW"); pthread_mutex_lock(&android_app->mutex); android_app->window = android_app->pendingWindow; pthread_cond_broadcast(&android_app->cond); @@ -114,7 +108,7 @@ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { break; case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); + LOGV("APP_CMD_TERM_WINDOW"); pthread_cond_broadcast(&android_app->cond); break; @@ -122,7 +116,7 @@ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { case APP_CMD_START: case APP_CMD_PAUSE: case APP_CMD_STOP: - LOGV("activityState=%d\n", cmd); + LOGV("activityState=%d", cmd); pthread_mutex_lock(&android_app->mutex); android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); @@ -130,14 +124,14 @@ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { break; case APP_CMD_CONFIG_CHANGED: - LOGV("APP_CMD_CONFIG_CHANGED\n"); + LOGV("APP_CMD_CONFIG_CHANGED"); AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); print_cur_config(android_app); break; case APP_CMD_DESTROY: - LOGV("APP_CMD_DESTROY\n"); + LOGV("APP_CMD_DESTROY"); android_app->destroyRequested = 1; break; } @@ -146,7 +140,7 @@ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { switch (cmd) { case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); + LOGV("APP_CMD_TERM_WINDOW"); pthread_mutex_lock(&android_app->mutex); android_app->window = NULL; pthread_cond_broadcast(&android_app->cond); @@ -154,7 +148,7 @@ void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { break; case APP_CMD_SAVE_STATE: - LOGV("APP_CMD_SAVE_STATE\n"); + LOGV("APP_CMD_SAVE_STATE"); pthread_mutex_lock(&android_app->mutex); android_app->stateSaved = 1; pthread_cond_broadcast(&android_app->cond); @@ -188,7 +182,7 @@ static void android_app_destroy(struct android_app* android_app) { static void process_input(struct android_app* app, struct android_poll_source* source) { AInputEvent* event = NULL; while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { - LOGV("New input event: type=%d\n", AInputEvent_getType(event)); + LOGV("New input event: type=%d", AInputEvent_getType(event)); if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { continue; } @@ -241,9 +235,8 @@ static void* android_app_entry(void* param) { // -------------------------------------------------------------------- static struct android_app* android_app_create(ANativeActivity* activity, - void* savedState, size_t savedStateSize) { - struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); - memset(android_app, 0, sizeof(struct android_app)); + void* savedState, size_t savedStateSize) { + struct android_app* android_app = calloc(1, sizeof(struct android_app)); android_app->activity = activity; pthread_mutex_init(&android_app->mutex, NULL); @@ -280,7 +273,7 @@ static struct android_app* android_app_create(ANativeActivity* activity, static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { - LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); + LOGE("Failure writing android_app cmd: %s", strerror(errno)); } } @@ -333,26 +326,30 @@ static void android_app_free(struct android_app* android_app) { free(android_app); } +static struct android_app* ToApp(ANativeActivity* activity) { + return (struct android_app*) activity->instance; +} + static void onDestroy(ANativeActivity* activity) { - LOGV("Destroy: %p\n", activity); - android_app_free((struct android_app*)activity->instance); + LOGV("Destroy: %p", activity); + android_app_free(ToApp(activity)); } static void onStart(ANativeActivity* activity) { - LOGV("Start: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); + LOGV("Start: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_START); } static void onResume(ANativeActivity* activity) { - LOGV("Resume: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); + LOGV("Resume: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_RESUME); } static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { - struct android_app* android_app = (struct android_app*)activity->instance; - void* savedState = NULL; + LOGV("SaveInstanceState: %p", activity); - LOGV("SaveInstanceState: %p\n", activity); + struct android_app* android_app = ToApp(activity); + void* savedState = NULL; pthread_mutex_lock(&android_app->mutex); android_app->stateSaved = 0; android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); @@ -373,69 +370,89 @@ static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { } static void onPause(ANativeActivity* activity) { - LOGV("Pause: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); + LOGV("Pause: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_PAUSE); } static void onStop(ANativeActivity* activity) { - LOGV("Stop: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); + LOGV("Stop: %p", activity); + android_app_set_activity_state(ToApp(activity), APP_CMD_STOP); } static void onConfigurationChanged(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("ConfigurationChanged: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); + LOGV("ConfigurationChanged: %p", activity); + android_app_write_cmd(ToApp(activity), APP_CMD_CONFIG_CHANGED); +} + +static void onContentRectChanged(ANativeActivity* activity, const ARect* r) { + LOGV("ContentRectChanged: l=%d,t=%d,r=%d,b=%d", r->left, r->top, r->right, r->bottom); + struct android_app* android_app = ToApp(activity); + pthread_mutex_lock(&android_app->mutex); + android_app->contentRect = *r; + pthread_mutex_unlock(&android_app->mutex); + android_app_write_cmd(ToApp(activity), APP_CMD_CONTENT_RECT_CHANGED); } static void onLowMemory(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("LowMemory: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); + LOGV("LowMemory: %p", activity); + android_app_write_cmd(ToApp(activity), APP_CMD_LOW_MEMORY); } static void onWindowFocusChanged(ANativeActivity* activity, int focused) { - LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); - android_app_write_cmd((struct android_app*)activity->instance, - focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); + LOGV("WindowFocusChanged: %p -- %d", activity, focused); + android_app_write_cmd(ToApp(activity), focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); } static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowCreated: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, window); + LOGI("NativeWindowCreated: %p -- %p", activity, window); + android_app_set_window(ToApp(activity), window); } static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, NULL); + LOGI("NativeWindowDestroyed: %p -- %p", activity, window); + android_app_set_window(ToApp(activity), NULL); +} + +static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) { + LOGI("NativeWindowRedrawNeeded: %p -- %p", activity, window); + android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_REDRAW_NEEDED); +} + +static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) { + LOGI("NativeWindowResized: %p -- %p", activity, window); + android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_RESIZED); } static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueCreated: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, queue); + LOGV("InputQueueCreated: %p -- %p", activity, queue); + android_app_set_input(ToApp(activity), queue); } static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, NULL); + LOGV("InputQueueDestroyed: %p -- %p", activity, queue); + android_app_set_input(ToApp(activity), NULL); } __attribute__((visibility("default"))) void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) { - LOGV("Creating: %p\n", activity); + LOGV("Creating: %p", activity); + + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onContentRectChanged = onContentRectChanged; activity->callbacks->onDestroy = onDestroy; - activity->callbacks->onStart = onStart; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + activity->callbacks->onLowMemory = onLowMemory; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; + activity->callbacks->onNativeWindowResized = onNativeWindowResized; + activity->callbacks->onPause = onPause; activity->callbacks->onResume = onResume; activity->callbacks->onSaveInstanceState = onSaveInstanceState; - activity->callbacks->onPause = onPause; + activity->callbacks->onStart = onStart; activity->callbacks->onStop = onStop; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - activity->callbacks->onLowMemory = onLowMemory; activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; activity->instance = android_app_create(activity, savedState, savedStateSize); } diff --git a/util/android/third_party/android_native_app_glue.h b/util/android/third_party/android_native_app_glue.h index c1e4d3cb47..304815f355 100644 --- a/util/android/third_party/android_native_app_glue.h +++ b/util/android/third_party/android_native_app_glue.h @@ -12,7 +12,6 @@ * 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 _ANDROID_NATIVE_APP_GLUE_H @@ -49,7 +48,7 @@ extern "C" { * * 2/ android_main() receives a pointer to a valid "android_app" structure * that contains references to other important objects, e.g. the - * ANativeActivity obejct instance the application is running in. + * ANativeActivity object instance the application is running in. * * 3/ the "android_app" object holds an ALooper instance that already * listens to two important things: @@ -87,17 +86,18 @@ struct android_app; * Data associated with an ALooper fd that will be returned as the "outData" * when that source has data ready. */ -struct android_poll_source { +struct android_poll_source +{ // The identifier of this source. May be LOOPER_ID_MAIN or // LOOPER_ID_INPUT. int32_t id; // The android_app this ident is associated with. - struct android_app* app; + struct android_app *app; // Function to call to perform the standard processing of data from // this source. - void (*process)(struct android_app* app, struct android_poll_source* source); + void (*process)(struct android_app *app, struct android_poll_source *source); }; /** @@ -108,25 +108,26 @@ struct android_poll_source { * VM, although it will need to be in order to make JNI calls any * Java objects. */ -struct android_app { +struct android_app +{ // The application can place a pointer to its own state object // here if it likes. - void* userData; + void *userData; // Fill this in with the function to process main app commands (APP_CMD_*) - void (*onAppCmd)(struct android_app* app, int32_t cmd); + void (*onAppCmd)(struct android_app *app, int32_t cmd); // Fill this in with the function to process input events. At this point // the event has already been pre-dispatched, and it will be finished upon // return. Return 1 if you have handled the event, 0 for any default // dispatching. - int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); + int32_t (*onInputEvent)(struct android_app *app, AInputEvent *event); // The ANativeActivity object instance that this app is running in. - ANativeActivity* activity; + ANativeActivity *activity; // The current configuration the app is running in. - AConfiguration* config; + AConfiguration *config; // This is the last instance's saved state, as provided at creation time. // It is NULL if there was no state. You can use this as you need; the @@ -136,18 +137,18 @@ struct android_app { // at which point they will be initialized to NULL and you can malloc your // state and place the information here. In that case the memory will be // freed for you later. - void* savedState; + void *savedState; size_t savedStateSize; // The ALooper associated with the app's thread. - ALooper* looper; + ALooper *looper; // When non-NULL, this is the input queue from which the app will // receive user input events. - AInputQueue* inputQueue; + AInputQueue *inputQueue; // When non-NULL, this is the window surface that the app can draw in. - ANativeWindow* window; + ANativeWindow *window; // Current content rectangle of the window; this is the area where the // window's content should be placed to be seen by the user. @@ -179,12 +180,13 @@ struct android_app { int stateSaved; int destroyed; int redrawNeeded; - AInputQueue* pendingInputQueue; - ANativeWindow* pendingWindow; + AInputQueue *pendingInputQueue; + ANativeWindow *pendingWindow; ARect pendingContentRect; }; -enum { +enum +{ /** * Looper data ID of commands coming from the app's main thread, which * is returned as an identifier from ALooper_pollOnce(). The data for this @@ -209,7 +211,8 @@ enum { LOOPER_ID_USER = 3, }; -enum { +enum +{ /** * Command from main thread: the AInputQueue has changed. Upon processing * this command, android_app->inputQueue will be updated to the new queue @@ -315,32 +318,37 @@ enum { * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next * app command message. */ -int8_t android_app_read_cmd(struct android_app* android_app); +int8_t android_app_read_cmd(struct android_app *android_app); /** * Call with the command returned by android_app_read_cmd() to do the * initial pre-processing of the given command. You can perform your own * actions for the command after calling this function. */ -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); +void android_app_pre_exec_cmd(struct android_app *android_app, int8_t cmd); /** * Call with the command returned by android_app_read_cmd() to do the * final post-processing of the given command. You must have done your own * actions for the command before calling this function. */ -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); +void android_app_post_exec_cmd(struct android_app *android_app, int8_t cmd); /** - * Dummy function you can call to ensure glue code isn't stripped. + * No-op function that used to be used to prevent the linker from stripping app + * glue code. No longer necessary, since __attribute__((visibility("default"))) + * does this for us. */ -void app_dummy(void); +__attribute__(( + deprecated("Calls to app_dummy are no longer necessary. See " + "https://github.com/android-ndk/ndk/issues/381."))) void +app_dummy(void); /** * This is the function that application code must implement, representing * the main entry to the app. */ -extern void android_main(struct android_app* app); +extern void android_main(struct android_app *app); #ifdef __cplusplus } |